<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9566863</id><updated>2023-06-26T08:26:24.563+00:00</updated><category term="Agile"/><category term="Clean code"/><category term="Code Quality"/><category term="Development"/><category term="Acceptance Critiera"/><category term="Certification"/><category term="Creativity"/><category term="DevOps"/><category term="Personal Development"/><category term="Product Owner"/><category term="Quality"/><category term="TDD"/><category term="Testing"/><category term="Unit Testing"/><category term="AI"/><category term="Azure"/><category term="Cloud"/><category term="Developer Tips"/><category term="Innovation"/><category term="Money &amp; Business"/><category term="Society"/><category term="business"/><category term="stu"/><category term="technology"/><category term=".NET"/><category term="Architecture"/><category term="Art"/><category term="Automation"/><category term="C#"/><category term="CSS"/><category term="ChatGPT"/><category term="Debugging"/><category term="Deployment"/><category term="Economy"/><category term="Gaming"/><category term="Learning"/><category term="NuGet"/><category term="Object Oriented Programming"/><category term="Product Development"/><category term="SOLID"/><category term="SRP"/><category term="Technical Debt"/><category term="Visual Studio"/><category term="abundance"/><category term="async"/><category term="business ideas"/><category term="capitalism"/><category term="efficiency"/><category term="future"/><category term="ideas"/><category term="improve"/><category term="money"/><category term="processes"/><category term="productivity"/><category term="scarcity"/><category term="socialism"/><title type='text'>stuartdobson.net</title><subtitle type='html'>.NET/Azure/AI Developer</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default?start-index=26&amp;max-results=25'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9566863.post-5984358628124554162</id><published>2023-05-23T03:53:00.007+00:00</published><updated>2023-05-23T03:54:04.536+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><title type='text'>Story Points are Utter Nonsense</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigNPOzVsHAghJ_DfKTuepyV3kEOQ60fcIko-mkZHned7H9Z0efM7lduc3IzfIU0OVtrP1cnVmB-XDA0lcSaUdh2D14PC2dBZhidUtUET-phF6xdGa2RVweQ1u4cGG-ykNMUtvfG7zO-8SIZW79udCSzWVTwoE-E4qsuvP8M_VAv0bjwHWWNs0/s1366/411a8a9ee0c93ad78a58e4670e37588c700c027b-1920x1080.webp&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;768&quot; data-original-width=&quot;1366&quot; height=&quot;360&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigNPOzVsHAghJ_DfKTuepyV3kEOQ60fcIko-mkZHned7H9Z0efM7lduc3IzfIU0OVtrP1cnVmB-XDA0lcSaUdh2D14PC2dBZhidUtUET-phF6xdGa2RVweQ1u4cGG-ykNMUtvfG7zO-8SIZW79udCSzWVTwoE-E4qsuvP8M_VAv0bjwHWWNs0/w640-h360/411a8a9ee0c93ad78a58e4670e37588c700c027b-1920x1080.webp&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;For over a decade, I&#39;ve lived a lie. &lt;/p&gt;&lt;p&gt;I made myself believe that Agile Story points made sense. &lt;/p&gt;&lt;p&gt;I rationalised it like we all did.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;i&gt;&quot;They map to complexity, not time&quot;. &lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Yet we spend hours on Sprint Planning meetings deciding how many jobs we can fit into a Sprint - &lt;em&gt;a unit of time&lt;/em&gt;. Also - doesn&#39;t complexity relate to time?&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;They&#39;re a rough guide, they&#39;re not supposed to be accurate.&quot; &lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;How on Earth did we end up with a unit of measure that is &quot;not supposed to be accurate&quot;?&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;It depends on experience of the person doing the job.&quot; &lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;This is like saying the length of a centimeter depends on the tape measure you&#39;re using.&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;They&#39;re a measure of&amp;nbsp;&lt;b&gt;relative &lt;/b&gt;complexity.&quot; &lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;Relative to what? Another story you did which didn&#39;t have an accurate estimate?&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;We use shirt sizes/Fibonacci/animals/fruit.&quot; &lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;Is this supposed to make it easier to understand? Why can&#39;t I give a task 4 points?&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;We have to agree on size before we can move on.&quot; &lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;Yes, let&#39;s ensure the contractor watering the plants gets a say on this.&lt;/p&gt;&lt;blockquote&gt;&lt;i&gt;&quot;Planning poker helps us find a consensus.&quot;&lt;/i&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;I guess it does, once everyone is worn down enough to just agree. &lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw_Yc5CLdXxeNkY0TjTV7fCVQw3PjUfyPIAoBemgs_ygXSTjd_0Ft3BEKR7NoICMmDuSI1JIcn7-wJUi863KEUgTn4hqAam_UD79eSeJ8_f_5AifnbNflu9WcskjqRpVkSHPqFPVxJkRYJdTIBBKIS-EcU-bwGZlHJmQI81ZQeWukHpTzZmyw/s418/Untitled.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;121&quot; data-original-width=&quot;418&quot; height=&quot;116&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw_Yc5CLdXxeNkY0TjTV7fCVQw3PjUfyPIAoBemgs_ygXSTjd_0Ft3BEKR7NoICMmDuSI1JIcn7-wJUi863KEUgTn4hqAam_UD79eSeJ8_f_5AifnbNflu9WcskjqRpVkSHPqFPVxJkRYJdTIBBKIS-EcU-bwGZlHJmQI81ZQeWukHpTzZmyw/w400-h116/Untitled.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt; &lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;A recent discussion highlighted the absurdity. I asked people to define what story points were, and just like the multiple meetings I&#39;ve had over many years, it was clear that nobody could agree.&lt;/p&gt;&lt;p&gt;I got the usual selection of contradictions and confusion. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Story points have no unit of value&lt;/li&gt;&lt;li&gt;Story points are a &lt;em&gt;non standard&lt;/em&gt; unit of value(?)&lt;/li&gt;&lt;li&gt;They&#39;re team specific, so they don&#39;t map to anything&lt;/li&gt;&lt;li&gt;They don&#39;t map to time, but they do map to a sprint, which is time&lt;/li&gt;&lt;li&gt;They map to complexity, but how much depends on the experience of who is doing the job, and the maturity of the team, which changes over time.&lt;/li&gt;&lt;li&gt;They&#39;re only supposed to be used for Epics, and Stories are estimated in time &lt;/li&gt;&lt;li&gt;A Story point is like a chicken&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Yes, that was a legitimate answer from someone attempting to explain what a story point was. &lt;/p&gt;&lt;p&gt;&lt;em&gt;It&#39;s like a chicken. &lt;/em&gt;&lt;/p&gt;&lt;p&gt;This is a real thing a human said: &lt;/p&gt;&lt;blockquote&gt;&lt;em&gt;&quot;I once had a Scrum consultant working with our team who said a story point can be a chicken if you wanted. Find a story that the team can say is a very simple piece of work and call that your chicken. This chicken is then 1 story point. A story that would be twice as difficult or complex would be a two-chicken story (or 2 story points). It&#39;s over-simplified, but perhaps you get the point.&quot;&lt;/em&gt;&lt;/blockquote&gt;&lt;p&gt;Erm, sorry, but I don&#39;t think I do...&lt;/p&gt;&lt;p&gt;Agile is a cult. This is evident in the explanations which pervade this space that are often repeated ad nauseam. One of these explanations becomes our rationalistion: &quot;It&#39;s Agile. It&#39;s flexible - you can do it how you want.&quot;&lt;/p&gt;&lt;p&gt;It&#39;s time we admit that it doesn&#39;t work and it&#39;s really just a cocktail of nonsense, designed to put a framework around what is, in the end, an impossibly hard thing to plan.&lt;/p&gt;&lt;p&gt;I&#39;m going to invent a new system of organising workloads. You have planning meetings once every 13 days unless there&#39;s a full moon. In those meetings you can play Snakes and Ladders to determine the &quot;relative complexity&quot; of a ticket. Then you throw that number out, and just do the job anyway. Every 15 minutes someone has to stand up and shout &quot;Bingo&quot;. Then someone else picks up the ball. &lt;/p&gt;&lt;p&gt;Actually, this makes as much sense as our Agile rituals, so it&#39;ll probably take off. &lt;/p&gt;&lt;p&gt;I apologise to the workers of 2040.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/5984358628124554162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2023/05/story-points-are-utter-nonsense.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5984358628124554162'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5984358628124554162'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2023/05/story-points-are-utter-nonsense.html' title='Story Points are Utter Nonsense'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigNPOzVsHAghJ_DfKTuepyV3kEOQ60fcIko-mkZHned7H9Z0efM7lduc3IzfIU0OVtrP1cnVmB-XDA0lcSaUdh2D14PC2dBZhidUtUET-phF6xdGa2RVweQ1u4cGG-ykNMUtvfG7zO-8SIZW79udCSzWVTwoE-E4qsuvP8M_VAv0bjwHWWNs0/s72-w640-h360-c/411a8a9ee0c93ad78a58e4670e37588c700c027b-1920x1080.webp" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-7932432770731110156</id><published>2023-01-07T23:05:00.003+00:00</published><updated>2023-01-12T23:59:14.010+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="ChatGPT"/><category scheme="http://www.blogger.com/atom/ns#" term="Developer Tips"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="productivity"/><title type='text'>6 Ways ChatGPT Can Help You Code</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;/span&gt;ChatGPT is blowing up at the moment, and for good reason. Its capabilities are unlike anything we&#39;ve ever seen.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Will it take our jobs as developers? No. But, if used correctly, it will transform them completely. Here&#39;s how I am already using ChatGPT to turbocharge my productivity. It&#39;s fair to say if you&#39;re not using this, you&#39;re going to be at a significant disadvantage.&lt;/p&gt;&lt;p&gt;Here&#39;s just a few ways you can use ChatGPT to rocket boost your development work.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Provide a starting point&lt;/span&gt;&lt;/p&gt;&lt;p&gt;If you know what your code needs to do, ChatGPT can quickly fill out the functionality for you:&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 783px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;783&quot; src=&quot;https://lh4.googleusercontent.com/V7adPYMJpknEA7mijYPkxBNaq-2wKNg8y83wt8Tb3tFFZ4IytWJHTkKBiByuuB54-n6-o7q25vZOYyNl7c2a4Ohxrd1ZGuHXp5GmgFaUNLzBcK9mz-ktUcqRfbWVpoRAs5roFRtT8hOb337mVIR2qyVovNlV-mKovgYmJJdqheLqJ5GTyuQja4LgI4Dvjg&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 256px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;256&quot; src=&quot;https://lh4.googleusercontent.com/ERdj2hPPaFgJT4EfJkdla9DyQX_MNZlofbew2cQIlqwVuWBJMPHNwXr3m3dx0g4xcFJU3BuTW4XdWDznkNZxhH7GymJRRxOTJEvDq6qUlOdQ2dscDQuezERIRJYlJHRypAxU4EM3edlFNGN6cL_Fx5i9bLCe8CZ_uGPf_h5ufi-52dLCWBItK3RrjDqbwQ&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Understanding code&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;&lt;br /&gt;A simple example but a great way to get some context on badly named or hard to follow functions.It’s also very good at explaining the different decision paths and giving useful examples. &lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 445px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;445&quot; src=&quot;https://lh6.googleusercontent.com/SmREBk7fusX3gnMq206PFZDm7E6ZkbdEat1ZTZ7PIKkY0MJsqL1_-1mqBCueQ4tc1X8LlMo0YishcrkvFtUYPCK94rbrqiz45dqp2JPQbC8atcVPHtO_9e1XbMStKEMxGGbAoIAJyMHbpboZZ-Ygg4weIAh6VTXv_e0QFNXbrDwScGXxfgh-Ar-nASnynQ&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Improving Code&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;Add more functionality to your code based on your suggestions: &lt;br /&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 637px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;637&quot; src=&quot;https://lh3.googleusercontent.com/mLQSUQ4RiCY_9wT8bqqW7RhibAcCTR8mk4avM1E9EqQe2Ztrr9sjFTFtTP65F9y59OJw40cgDOf5NWTXJfl7EuiuzYQoTu93EIiBqtXRKH25HVQmQ5uzXCKEz4PAiCyp2nTqv7-2Bcx9nZ_BG1YiCD0kthvrErFPyS5YudZbU6m3E4wmUn9MfO_MTjXvGg&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Give some more suggestions for improvements:&amp;nbsp; &lt;br /&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 936px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;936&quot; src=&quot;https://lh3.googleusercontent.com/k7BkkVYu7MUGctRRxrX1UfzeNymDUW-81xKIIE4Q27cWNIXITz2vRabGQFhqXvX9_hPNPzPINhentiyJJPacWVfvb_NknT4GJpCt6FA2BE5Wy91gxMGW2UE6oZkfDuls_sunzNuG0no_2YkWOmF9zJjfVdob_TxkhEBWVntRzFGlfuxiInDAj1qAXkhdTQ&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Simplifying code, with explanations&lt;/span&gt;&lt;/h1&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;I originally wrote this method (a looong time ago), and wanted to see how ChatGPT could make it simpler.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;div style=&quot;background-color: #293134; color: #e0e2e4; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;ConvertImageToThumbnailJPG&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Stream&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; input, &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Stream&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; output, &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; thumbnailsize = &lt;/span&gt;&lt;span style=&quot;color: #ffcd22;&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; width;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; height;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; originalImage = &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Bitmap&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(input);&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Width&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Height&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; width = thumbnailsize;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; height = thumbnailsize * &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Height&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; / &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Width&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;else&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; height = thumbnailsize;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; width = thumbnailsize * &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Width&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; / &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;originalImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Height&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Bitmap&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; thumbnailImage = &lt;/span&gt;&lt;span style=&quot;color: #93c763; font-weight: bold;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;try&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thumbnailImage = &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Bitmap&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(width, height);&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; graphics = &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;FromImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(thumbnailImage))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;InterpolationMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;InterpolationMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;HighQualityBicubic&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;SmoothingMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;SmoothingMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;AntiAlias&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;PixelOffsetMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;PixelOffsetMode&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;HighQuality&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;graphics&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;DrawImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(originalImage, &lt;/span&gt;&lt;span style=&quot;color: #ffcd22;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #ffcd22;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;, width, height);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;thumbnailImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Save&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;(output, &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;ImageFormat&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Jpeg&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;finally&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #93c763;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt; (thumbnailImage != &lt;/span&gt;&lt;span style=&quot;color: #93c763; font-weight: bold;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;thumbnailImage&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #678cb1;&quot;&gt;Dispose&lt;/span&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #e0e2e4;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 797px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;797&quot; src=&quot;https://lh6.googleusercontent.com/w2-PeSZ1SjWKfLpyi7K8ZRgpExQeIh5pElCiVcLa-GDhuGJbpxEoTzA5D_S9wGKRk_j28axaTgyWaVsn6ETHsSPws6QKZpoUskebi81_-N1_P_LHCY8GYnESKEt8qO9W5Lgh8IrO9gi59XEN8Cipb8aBq4LG-coTVs5PbXL93LwIdbgzRbSriGmYQUMtLA&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Documenting Code&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;ChatGPT can easily add comments based on what the code is doing.&amp;nbsp; &lt;br /&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 904px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;904&quot; src=&quot;https://lh5.googleusercontent.com/9AwKajMxsv9x015yFDxxmz8pVlaq8M1Uxa5s9AX_opoK14bB7B06oNZr1lKUIzQycVtW8JVgSmNklVOL6ps7T_-0RvJagk85u3IJfISrMB5PFql3YRtqjmeSf_xR72OGvnJxMTxFTrHYf-bdjSElXVCEnxA9SEarHKD_UVIXyjCXeWzUYZvrcqw2aOcY_Q&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Writing Tests&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;And now, for the biggest time saving operation - automatically defining test cases, AND writing those tests:&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 857px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;857&quot; src=&quot;https://lh4.googleusercontent.com/TON4IemQ5WQ5Rwg2gd1993ePJlqLZQefAV4BQKZqsajYEcaZ9emdd6qWF4OOy0OBaX2poIkq41-rJ4QwkGvPzfNslFDD6i_cdQPvCsST7vWwoCXva21yx0ESsfVaeappd4CJnAsJm2rr_y2FBGv_aTsaKSAdvPdMpr9xTChjIs2aL7HvwLel-fM0bs_1rg&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 977px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;977&quot; src=&quot;https://lh6.googleusercontent.com/Mn6RYaefrgcz5CTnj2IfPiR6s6Yd3KLb5Gn7GbLoB6pyusPNECSj1v1aC8SCPv0aAhDpNtFmWj9jh6EUTYnE9IrBcPX_Rj5VPp8LY-vuXfRUAQsU2ZulO_qxdVjQ2kPhT02duzWI4i7RO9etUKVFB3ow58xvjGIjgUykE1wOLKdzXskGC6SwlrQGuGMJ7g&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;It continued to give me all the tests I needed. This alone saved me a couple of hours.&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Be careful relying on ChatGPT&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;You’ll notice some issues in the generated code - test cases 3 and 5 for example have inputs and assumptions which are not quite right. However, it’s trivial to change this in the real code. The important thing is that you are aware that ChatGPT often makes mistakes and you must check its work. &lt;br /&gt;&lt;br /&gt;It can also be a little stupid at times:&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span style=&quot;border: medium none; display: inline-block; height: 515px; overflow: hidden; width: 624px;&quot;&gt;&lt;img height=&quot;515&quot; src=&quot;https://lh3.googleusercontent.com/LjZmsO2GN0mWuaVOyWWPwwZl1xBjAVzEjpc3IAg8Dpm_Cc50iZVuStS5aD6xOpnAFKHdKQ4tAnKDCchjcffpHx91S0vWQ4TfsGxHExzwX9uAcFDsVomPpne4mtMEkge2nSKG188-FBF-0EdrnNyCnvUO7GSElki4xW_ALs-1SA7lVV4TDgtYFdgZk1k6Fg&quot; style=&quot;margin-left: 0px; margin-top: 0px;&quot; width=&quot;624&quot; /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;A great companion&lt;/span&gt;&lt;/h1&gt;ChatGPT is not going to do all your work for you. But it can be an excellent partner - helping with a lot of grunt work and providing comprehensive suggestions. It’s up to you to vet those suggestions. &lt;br /&gt;&lt;br /&gt;For simple code, this can be a massive time saver. For more complex code, be careful that it doesn’t give you more work by providing complex solutions which don’t quite work. It’s best to break the code down as much as possible as it seems to cope much better, most of the time. &lt;h1 dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 6pt; margin-top: 24pt;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: black; font-family: Arial; font-size: 18pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;&quot;&gt;Productivity 100x&lt;/span&gt;&lt;/h1&gt;Don’t think of ChatGPT as a threat to your job as a developer. Think of it as a critical tool, which can help you increase your productivity by several orders of magnitude.. &lt;br /&gt;&lt;br /&gt;Anyone not using it will find themselves left behind. &lt;br /&gt;&lt;br /&gt;Start learning how to get the most out of &lt;a href=&quot;https://chat.openai.com/chat&quot;&gt;ChatGPT&lt;/a&gt; today.</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/7932432770731110156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2023/01/6-ways-chatgpt-can-help-you-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/7932432770731110156'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/7932432770731110156'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2023/01/6-ways-chatgpt-can-help-you-code.html' title='6 Ways ChatGPT Can Help You Code'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh4.googleusercontent.com/V7adPYMJpknEA7mijYPkxBNaq-2wKNg8y83wt8Tb3tFFZ4IytWJHTkKBiByuuB54-n6-o7q25vZOYyNl7c2a4Ohxrd1ZGuHXp5GmgFaUNLzBcK9mz-ktUcqRfbWVpoRAs5roFRtT8hOb337mVIR2qyVovNlV-mKovgYmJJdqheLqJ5GTyuQja4LgI4Dvjg=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-5927747183005147580</id><published>2022-11-13T23:00:00.008+00:00</published><updated>2022-11-13T23:00:00.175+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Automation"/><category scheme="http://www.blogger.com/atom/ns#" term="Code Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing"/><title type='text'>Why chasing Unit Test coverage can be a bad idea</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRS4Qb0FsPDBvlPYAy9aDZxUN_WHsW_VTYAAqLSjZUkGVg5O7fdqbYHka8QP-CBTm7bI5FW382AVPEWlnNiB3yaFGzPU7_8FcUuIBHvjVrQIRPKAC2pfEZWWeF5M509ldSzWTo8D9VuyxlFpYmyPpx2p-6wLWKHl1maUnNN_Vxf_fq0Wbupg/s1200/unittestcov.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;400&quot; data-original-width=&quot;1200&quot; height=&quot;214&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRS4Qb0FsPDBvlPYAy9aDZxUN_WHsW_VTYAAqLSjZUkGVg5O7fdqbYHka8QP-CBTm7bI5FW382AVPEWlnNiB3yaFGzPU7_8FcUuIBHvjVrQIRPKAC2pfEZWWeF5M509ldSzWTo8D9VuyxlFpYmyPpx2p-6wLWKHl1maUnNN_Vxf_fq0Wbupg/w640-h214/unittestcov.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;In the long running battle between management chasing metrics and developers just trying to get the job done, (hi boss!)&amp;nbsp; I wanted to provide some less obvious examples of why chasing code coverage is a damaging process.&amp;nbsp;&lt;/p&gt;&lt;h2&gt;&lt;strong&gt;Why Unit Test Code Coverage targets are bad&lt;/strong&gt;&lt;/h2&gt;&lt;h3&gt;&lt;strong&gt;Code Coverage can be gamed, incentivising low quality tests&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;If the coverage percentage is all that matters, there are many ways to increase that number without actually improving the quality and reliability of the code. Having a test doesn’t mean no bugs - it just means the code is being run by a test, that the pathways through the code are exercised by another piece of code. &lt;/p&gt;&lt;p&gt;There’s not really any link in these tests to importance of functionality, or even any consideration of code doing the right thing, just that it’s being exercised.&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Tests add a maintenance burden&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;In the writing of low value tests written only to satisfy KPIs, developers are actually making more work for themselves in the future.&amp;nbsp;&lt;/p&gt;&lt;p&gt;All code adds a maintenance burden. Tests are code so adding tests adds to this burden. If they’re not valuable, they’re detrimental.&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Chasing coverage leads to more brittle tests&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The more coverage you have, the more brittle your tests actually become. By covering every internal path of a method, you are tightly coupling the tests with the implementation details.&amp;nbsp;&lt;/p&gt;&lt;p&gt;This goes against the spirit of testing. You should be testing the functionality of the code - the inputs, outputs, and decisions it makes, and the edge cases.You don’t need to be too concerned with &lt;strong&gt;how &lt;/strong&gt;it makes those decisions.&amp;nbsp;&lt;/p&gt;&lt;p&gt;This in turn makes you write tests the right way - thinking about the desired functionality instead of the coverage.&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Give a false impression of robust code&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;It should be obvious but it’s often overlooked. High coverage, which as discussed leads to low quality tests which often don’t test the right things, gives a false sense of security. You may have 80% coverage but if the last 20% is all the business critical functionality, or vital areas of the code, this could be hiding big problems.&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Chasing metrics hides opportunities to improve the code quality&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Let’s remember why we write tests in the first place. It’s to have confidence that our code is meeting the requirements, can handle edge cases, and is free of bugs. By focusing on coverage, you are missing the opportunity to write tests which do this - tests which actually lead to better quality code.&lt;/p&gt;&lt;p&gt;Thinking about what scenarios you need to cover when writing code, encourages you to write the code in a testable way. If you write it in a testable way, you’ll be more likely to write tests - valuable tests. Better still, you’ll be more inclined to write the tests, or at least stubs of them, first (Test Driven Development).&lt;/p&gt;&lt;p&gt;If you write code and then add tests as an afterthought, you’ll probably focus on coverage instead of functionality, because you’ll be thinking about “adding tests” and increasing coverage - rather than thinking about the original intentions of the code.&lt;/p&gt;&lt;h2&gt;&lt;strong&gt;Why Code Coverage is good&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Despite all these issues, Code coverage has a place in software development and there are some benefits to monitoring it, as opposed to incentivising it.&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Identifies areas of low coverage&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;In combination with your knowledge of where important functionality lies, you can see where tests are needed. Without code coverage metrics, it’s pretty hard to do this.&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;Instills a culture of continually adding tests as you go&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Let’s not forget that we want to be writing tests. We’ll get good coverage just by doing it as a habit, and by monitoring the coverage, we’ll see it go down if we write code that’s untested. So this encourages us to keep up with writing tests as we add features, and helps us see when we’re not adding them.&lt;/p&gt;&lt;p&gt;This keeps test writing on everyone’s minds, and influences the culture to make people value tests.&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you’re not measuring, you don’t know if you’re improving!&lt;/p&gt;&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;This article is very much a developer’s perspective, but at the end of the day, code coverage is a Return on Investment decision. Care should be taken on where the coverage is increased. Writing tests for existing code should be done in a way that prioritises high value, low effort new tests.&lt;/p&gt;&lt;p&gt;Code coverage is a good thing in that it gives a picture of where you are, and helps you monitor your testing journey. It’s always problematic to incentivise metrics, or even push to maintain a level. But we should be mindful of the level of coverage.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Focus on code coverage detracts from why you should be writing tests in the first place. The important thing is that we build tests around requirements and edge cases - tests which exercise and document real life scenarios. Tests are not about lines of code covered. This is an indicator - not an incentive.&lt;/p&gt;&lt;p&gt;Writing tests is a very important part of software development. Do it for the right reasons, and it will be done well. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/5927747183005147580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2022/11/why-chasing-unit-test-coverage-can-be.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5927747183005147580'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5927747183005147580'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2022/11/why-chasing-unit-test-coverage-can-be.html' title='Why chasing Unit Test coverage can be a bad idea'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieRS4Qb0FsPDBvlPYAy9aDZxUN_WHsW_VTYAAqLSjZUkGVg5O7fdqbYHka8QP-CBTm7bI5FW382AVPEWlnNiB3yaFGzPU7_8FcUuIBHvjVrQIRPKAC2pfEZWWeF5M509ldSzWTo8D9VuyxlFpYmyPpx2p-6wLWKHl1maUnNN_Vxf_fq0Wbupg/s72-w640-h214-c/unittestcov.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-6655994676857858211</id><published>2022-09-12T11:34:00.006+00:00</published><updated>2022-09-12T11:43:14.725+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Azure"/><category scheme="http://www.blogger.com/atom/ns#" term="Certification"/><title type='text'>Microsoft Certified: Azure Fundamentals</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFMe5eTpZLu-1NpkDrzlLzuPZWjKKp1OWs5vS9hsdmLqxTv7cZr4ltVZo5nShPjB5LAWq6gy2CTzdPipcLix1zzspi7n0sLTrb7YdBsp9FiIf45Ks93E86zA5eCgtxI4piYQjMb1Ao1_nn3Uud8951NeNhtIQR4YE-tstePBqqAJwAod93coM/s600/microsoft-certified-azure-fundamentals.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;600&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFMe5eTpZLu-1NpkDrzlLzuPZWjKKp1OWs5vS9hsdmLqxTv7cZr4ltVZo5nShPjB5LAWq6gy2CTzdPipcLix1zzspi7n0sLTrb7YdBsp9FiIf45Ks93E86zA5eCgtxI4piYQjMb1Ao1_nn3Uud8951NeNhtIQR4YE-tstePBqqAJwAod93coM/s320/microsoft-certified-azure-fundamentals.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Another month, another Fundamentals exam 😄&lt;p&gt;&lt;/p&gt;&lt;p&gt;I got this one because it was free after doing some online training through Microsoft. But - it was about time I got it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I&#39;ve been using Azure since it came out but never got certified because there&#39;s a lot of Infrastructure stuff in the exams which don&#39;t particularly interest me as a developer. In saying that, I found the exam material high level enough to be interesting and I managed to fill in a few gaps.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Most notably - I enjoyed playing with the &lt;a href=&quot;https://infrastructuremap.microsoft.com/&quot; target=&quot;_blank&quot;&gt;Azure Infrastructure map&lt;/a&gt;. It&#39;s a cool visualisation tool that lets you explore all the Azure infrastructure, all the datacentres, undersea cables, even satellites. You can take a virtual tour of a datacentre and learn about Azure in space! Cool stuff. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/6655994676857858211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2022/09/microsoft-certified-azure-fundamentals.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/6655994676857858211'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/6655994676857858211'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2022/09/microsoft-certified-azure-fundamentals.html' title='Microsoft Certified: Azure Fundamentals'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFMe5eTpZLu-1NpkDrzlLzuPZWjKKp1OWs5vS9hsdmLqxTv7cZr4ltVZo5nShPjB5LAWq6gy2CTzdPipcLix1zzspi7n0sLTrb7YdBsp9FiIf45Ks93E86zA5eCgtxI4piYQjMb1Ao1_nn3Uud8951NeNhtIQR4YE-tstePBqqAJwAod93coM/s72-c/microsoft-certified-azure-fundamentals.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-1918177346366550219</id><published>2022-07-10T11:54:00.005+00:00</published><updated>2022-07-10T11:57:21.998+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Product Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Product Owner"/><category scheme="http://www.blogger.com/atom/ns#" term="Society"/><category scheme="http://www.blogger.com/atom/ns#" term="technology"/><title type='text'>Foundations of Humane Technology - Course completed</title><content type='html'>&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQb5oosTJm69gWuEzzTAh6n6oahUUPtdNecL1WcrrK-IbA_t0Kf261j5mGHLx2eNwPcdzgZXR13-dFX00VvihyBBWBfSMgvDkcbP_0kNxfHvj-8RdBbCE4RqDJIIMV0M5vKImR1ntlGoAnj0W1sYGR3AqtLQnmgDv2uSj1RwF2ortMcPoMdWQ/s800/61f3107aa02d0314ae8d5ee0_Mod5-Thumb.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;800&quot; height=&quot;480&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQb5oosTJm69gWuEzzTAh6n6oahUUPtdNecL1WcrrK-IbA_t0Kf261j5mGHLx2eNwPcdzgZXR13-dFX00VvihyBBWBfSMgvDkcbP_0kNxfHvj-8RdBbCE4RqDJIIMV0M5vKImR1ntlGoAnj0W1sYGR3AqtLQnmgDv2uSj1RwF2ortMcPoMdWQ/w640-h480/61f3107aa02d0314ae8d5ee0_Mod5-Thumb.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Back in January (has it been that long!) I completed the &lt;a href=&quot;https://app.participate.com/course-bundles/foundations-of-humane-technology/20a00320-edeb-4ffc-b43f-c394397deb3b&quot; target=&quot;_blank&quot;&gt;Foundations of Humane Technology&lt;/a&gt; course from the &lt;a href=&quot;https://www.humanetech.com/&quot; target=&quot;_blank&quot;&gt;Center of Humane Technology&lt;/a&gt;. You may have heard of them, they made the Netflix Documentary &quot;&lt;a href=&quot;https://www.humanetech.com/the-social-dilemma&quot; target=&quot;_blank&quot;&gt;The Social Dilemma&lt;/a&gt;&quot;. &lt;br /&gt;&lt;br /&gt;If you haven&#39;t watched the movie, it&#39;s well worth a watch, delving into the often devastating impacts of Social Media. &lt;br /&gt;&lt;br /&gt;The course explored how to build technology in a more responsible way to minimise the harmful consequences of the technology you build. It&#39;s perfect for technology oriented Product owners and developers like myself, requiring us to think about externalities and unintended consequences, and aligning our values with the products we build. &lt;br /&gt;&lt;br /&gt;I was made to reflect on how technology has impacted me personally, and realised how my health, cognition and attention were impacted by technology overuse.&lt;br /&gt;&lt;br /&gt;I was obliged to acknowledge that I am very privileged and lucky, I don’t have any major accessibility issues and my demographic allows me to avoid most prejudices. This led to reflecting on the injustices and oversights suffered by many and encouraged me to think about how I could improve my products to address these issues.&lt;br /&gt;&lt;br /&gt;One section, Creating Shared Understanding, was particularly interesting in highlighting the role technology has had, especially recently, in dividing society. But this section gave the opportunity to think about how we can improve this situation moving forward.&lt;br /&gt;&lt;br /&gt;For me the most compelling aspect of the course was the section on Minimising Harmful Consequences. Learning a lot about the consequences of various social media platforms, it was easy to conceptualise the problems that this course is trying to address. These consequences are numerous and are having significant long term impacts on society. I’d like to explore these topics in much more depth. &lt;br /&gt;&lt;br /&gt;The course concluded with “Helping People Thrive”. Not content with just reducing harm and injustice, we were pushed to consider how we would actually improve people’s lives with the technology we build. And not just improve their lives by giving them better content to look at - of course - but to truly improve people’s happiness, wellbeing, and community.&lt;br /&gt;&lt;br /&gt;By the end of the course I had clear goals for moving forward. &lt;br /&gt;&lt;br /&gt;As a software developer working with AI platforms I want to build awareness around these systems, showing people how they work and what they are doing. AI is often (rightfully) criticised for its controversial applications. I want to continue highlighting the dangers while also alleviating concerns where they are unfounded. In the products I develop I want it to be clear what is happening with users&#39; data, which parts of it are being subjected to AI analysis, why, and how. &lt;br /&gt;&lt;br /&gt;I’m also keen to teach other developers and product owners about the harms of certain user interfaces (e.g. autoplay) and advocate for better security and privacy in all technology.&lt;br /&gt;&lt;br /&gt;If you work in technology, I highly recommend this course. It’s free and took me about 15 hours.&lt;br /&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/1918177346366550219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2022/07/foundations-of-humane-technology-course.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/1918177346366550219'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/1918177346366550219'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2022/07/foundations-of-humane-technology-course.html' title='Foundations of Humane Technology - Course completed'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQb5oosTJm69gWuEzzTAh6n6oahUUPtdNecL1WcrrK-IbA_t0Kf261j5mGHLx2eNwPcdzgZXR13-dFX00VvihyBBWBfSMgvDkcbP_0kNxfHvj-8RdBbCE4RqDJIIMV0M5vKImR1ntlGoAnj0W1sYGR3AqtLQnmgDv2uSj1RwF2ortMcPoMdWQ/s72-w640-h480-c/61f3107aa02d0314ae8d5ee0_Mod5-Thumb.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-698660254562717820</id><published>2022-03-28T10:40:00.011+00:00</published><updated>2022-09-12T11:55:26.113+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="Azure"/><category scheme="http://www.blogger.com/atom/ns#" term="Certification"/><title type='text'> Microsoft Certified: Azure AI Fundamentals</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNcPMuS4GY9uH4IDC2BnSYug3xvZzahU9kyx7IRYjZ_3Tr-JFy1cdTE0yMC9DBdPd8DSfWTWd6WMaswoJ_4Z4BXS7ixm-908TE5_Scm-OUzCpY8kTOdOv_DvtRCj3EDwVoMadPRmZHW3h3Q0MzvNxaiNcbR-EYoQuIR2OTJr9KmhJjQznHNeI/s600/microsoft-certified-azure-ai-fundamentals.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;600&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNcPMuS4GY9uH4IDC2BnSYug3xvZzahU9kyx7IRYjZ_3Tr-JFy1cdTE0yMC9DBdPd8DSfWTWd6WMaswoJ_4Z4BXS7ixm-908TE5_Scm-OUzCpY8kTOdOv_DvtRCj3EDwVoMadPRmZHW3h3Q0MzvNxaiNcbR-EYoQuIR2OTJr9KmhJjQznHNeI/s320/microsoft-certified-azure-ai-fundamentals.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Woo!&amp;nbsp;&lt;p&gt;&lt;/p&gt;&lt;p&gt;This was by far one of the most fun exams I&#39;ve had to do.&amp;nbsp;&lt;/p&gt;&lt;p&gt;I&#39;ve learnt a really good overview of Microsoft&#39;s AI services. I learnt about Image recognition, Bot framework, Speech recognition, Language processing, Knowledge mining, and more.&amp;nbsp;&lt;/p&gt;&lt;p&gt;I&#39;ve worked a little with Microsoft&#39;s Cognitive Framework in the past. In 2016 my team won our company&#39;s Innovation Day prize for building an app which monitored employee happiness. We made it into a joke - Big Brother spying on you all day to determine your emotional state at work by taking a photo of you every few seconds and analysing your emotion. It was a joke, man.&lt;/p&gt;&lt;p&gt;Fast forward 5 years and there are companies out there doing this as a business now. How effective it is I&#39;m not sure. Given that I ran Hide the pain Harold through the Emotion Service and he got 99% happiness, I have my doubts.&lt;/p&gt;&lt;p&gt;Anyway, there is so much cool stuff you can do with the Azure AI tools. I recommend giving this &lt;a href=&quot;https://docs.microsoft.com/en-au/certifications/azure-ai-fundamentals/&quot; target=&quot;_blank&quot;&gt;exam overview&lt;/a&gt; a good look.&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/698660254562717820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2022/03/microsoft-certified-azure-ai.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/698660254562717820'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/698660254562717820'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2022/03/microsoft-certified-azure-ai.html' title=' Microsoft Certified: Azure AI Fundamentals'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNcPMuS4GY9uH4IDC2BnSYug3xvZzahU9kyx7IRYjZ_3Tr-JFy1cdTE0yMC9DBdPd8DSfWTWd6WMaswoJ_4Z4BXS7ixm-908TE5_Scm-OUzCpY8kTOdOv_DvtRCj3EDwVoMadPRmZHW3h3Q0MzvNxaiNcbR-EYoQuIR2OTJr9KmhJjQznHNeI/s72-c/microsoft-certified-azure-ai-fundamentals.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-671009830427424429</id><published>2021-10-04T05:27:00.027+00:00</published><updated>2022-03-25T00:26:56.544+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><category scheme="http://www.blogger.com/atom/ns#" term="Code Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing"/><title type='text'>Unit Tests - Keeping them clean and simple</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-KsdOLmXwmN0/YUvFLPyhL0I/AAAAAAABQQM/YEUsfITG26IKa-5laAwwz0XgCWNCzXDYgCPcBGAYYCw/s1200/top-tools-in-automated-testing.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;600&quot; data-original-width=&quot;1200&quot; height=&quot;320&quot; src=&quot;https://1.bp.blogspot.com/-KsdOLmXwmN0/YUvFLPyhL0I/AAAAAAABQQM/YEUsfITG26IKa-5laAwwz0XgCWNCzXDYgCPcBGAYYCw/w640-h320/top-tools-in-automated-testing.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Tests should be split up by behaviour&lt;/h2&gt;&lt;div class=&quot;reader-article-content&quot; dir=&quot;ltr&quot;&gt; 
  &lt;p&gt;One behaviour, one test. This means don&#39;t test more than one thing in a test. Ideally &lt;a href=&quot;https://www.linkedin.com/pulse/importance-good-acceptance-criteria-stuart-dobson&quot; target=&quot;_blank&quot;&gt;there should be Acceptance Criteria&lt;/a&gt;
 clarifying each expected behaviour. This gives you a solid starting 
point, but Unit tests can expand on these scenarios by covering edge 
cases.&lt;/p&gt; 
  &lt;p&gt;Telltale signs of breaking this guideline include:&lt;/p&gt; 
  &lt;ul&gt;&lt;li&gt;Multiple &quot;Act&quot; steps (this is a big sign)&lt;/li&gt;&lt;li&gt;Multiple asserts throughout a test&lt;/li&gt;&lt;li&gt;Multiple &lt;u&gt;unrelated&lt;/u&gt; asserts at the end of a test&lt;/li&gt;&lt;li&gt;Data is being changed after the Act step&lt;/li&gt;&lt;li&gt;Using the word &quot;correct&quot; in your test name - indicates vague expectations&lt;/li&gt;&lt;/ul&gt; 
  &lt;p&gt;Don&#39;t be afraid to create lots of test methods for a single 
scenario or unit under test, testing various behaviours. When writing 
unit tests, you can make a new class for each scenario, this gives you 
power over the TestInitialize/Cleanup methods, allowing you to keep your
 tests cleaner.&lt;/p&gt; 
  &lt;h2&gt;Readability is Everything&lt;/h2&gt; 
  &lt;p&gt;The number one thing to remember when writing tests is that they 
need to be clear. This means they should be simple and concise, and 
separated by requirement.&lt;/p&gt; 
  &lt;p&gt;Place the same importance on readability as you would for 
production code. We spend 10 times more time reading code than writing 
it. It needs to be extremely easy to read in order to be maintainable.&lt;/p&gt; 
  &lt;p&gt;By making the tests readable, you should immediately be able to see
 what your tests are doing, and easily see how the tests in a class 
differ from each other. So bear this in mind, especially in tests that 
require large amounts of data setup.&lt;/p&gt; 
  &lt;p&gt;Think about what the test does and ensure this is communicated clearly. You can do this in several ways:&lt;/p&gt; 
  &lt;h3&gt;Name of the Test&lt;/h3&gt; 
  &lt;p&gt;The industry standard format for naming tests is:&lt;/p&gt; 
  &lt;p&gt;UnitUnderTest_Scenario_Expectation&lt;/p&gt; 
  &lt;p&gt;for example:&lt;/p&gt; 
  &lt;p&gt;MyMethod_WhenNoResults_ReturnsException&lt;/p&gt; 
  &lt;p&gt;The reason for this is so that we can see at a glance what is being
 tested. We should be able to quickly discern &lt;b&gt;what &lt;/b&gt;the test is testing, 
what the &lt;b&gt;scenario &lt;/b&gt;is, and the &lt;b&gt;expectation&lt;/b&gt;.&lt;/p&gt; 
  &lt;p&gt;Using the word &quot;Correct&quot; in the expectation part is not ideal, 
because it does not make it clear what &quot;correct&quot; means. Be specific 
about what your test expects.&lt;/p&gt; 
  &lt;h3&gt;Test Description Tag&lt;/h3&gt; 
  &lt;p&gt;A clear name for the test is paramount, but if not enough 
information can be conveyed in the name, consider use of some kind of [Description] attribute or other labeling on the test to provide more information.&lt;/p&gt; 
  &lt;h3&gt;Comments&lt;/h3&gt; 
  &lt;p&gt;Throughout your test, consider the use of comments to make it clear
 why you are setting up data in that way, to highlight when you are 
performing the action, or anything else that may not be immediately 
clear. &lt;/p&gt; 
  &lt;h3&gt;Arrangement&lt;/h3&gt; 
  &lt;p&gt;Consider the format of a test:&lt;/p&gt; 
  &lt;ul&gt;&lt;li&gt;&lt;b&gt;Arrange&lt;/b&gt;: This is where you set up the data/objects that are required to perform the action.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Act&lt;/b&gt;: This is generally one line, where you call the method / unit under test, or perform the required action.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Assert&lt;/b&gt;: This is where you check that the expectation has been fulfilled.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt; 
  &lt;p&gt;You don&#39;t necessarily need to write&amp;nbsp;// Arrange/Act/Assert as 
comments but it should be clear where each step is happening. At the 
very least, leave an empty line between each of these sections.&lt;/p&gt; 
  &lt;p&gt;If you keep this arrangement in mind, you will find it easier to 
follow good testing practices and split tests correctly by behaviour. &lt;b&gt;All tests should have an action and an expectation, &lt;/b&gt;not all require setup&lt;b&gt;.&lt;/b&gt;&lt;/p&gt; 
  &lt;h3&gt;Abstract out large &quot;Arrange&quot; blocks&lt;/h3&gt; 
  &lt;p&gt;Keeping data setup areas short is a good way to improve 
readability. Nobody wants to look at large blocks of 
constuctors/initialisers. Importantly, it should be clear what is 
different about this data compared with the next test in the class.&lt;/p&gt; 
  &lt;p&gt;To keep arrange steps short and clean, feel free to create 
extension methods or other helper classes to carry out frequently 
performed data creation strategies.&lt;/p&gt; 
  &lt;h2&gt;In Summary&lt;/h2&gt; 
  &lt;p&gt;Unit tests should be clean and simple. Most importantly, they should clearly define 
the &lt;b&gt;action&lt;/b&gt; or &lt;b&gt;scenario&lt;/b&gt;, and the &lt;b&gt;expectation&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Remembering this will ensure that 
your tests are useful, easy to maintain, and help to document your code.
 &lt;/p&gt;
 
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/671009830427424429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2021/10/unit-tests-keeping-them-clean-and-simple.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/671009830427424429'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/671009830427424429'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2021/10/unit-tests-keeping-them-clean-and-simple.html' title='Unit Tests - Keeping them clean and simple'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-KsdOLmXwmN0/YUvFLPyhL0I/AAAAAAABQQM/YEUsfITG26IKa-5laAwwz0XgCWNCzXDYgCPcBGAYYCw/s72-w640-h320-c/top-tools-in-automated-testing.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-2578901688538175598</id><published>2021-10-01T01:30:00.003+00:00</published><updated>2022-03-25T00:27:25.584+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Acceptance Critiera"/><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><category scheme="http://www.blogger.com/atom/ns#" term="Product Owner"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Writing Good Acceptance Criteria</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-cAVerkoxjGs/YUvH5K4gaPI/AAAAAAABQQg/Z1anZbziFVsPbC9k5jPub24S4DMBwMnuwCLcBGAsYHQ/s1186/1532986745531.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;720&quot; data-original-width=&quot;1186&quot; height=&quot;388&quot; src=&quot;https://1.bp.blogspot.com/-cAVerkoxjGs/YUvH5K4gaPI/AAAAAAABQQg/Z1anZbziFVsPbC9k5jPub24S4DMBwMnuwCLcBGAsYHQ/w640-h388/1532986745531.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;As discussed in my last &lt;a href=&quot;https://blog.stuartdobson.net/2021/09/the-importance-of-good-acceptance.html&quot; target=&quot;_blank&quot;&gt;article&lt;/a&gt;,
 Writing good Acceptance Criteria gives the Agile team clarity and helps
 them work towards a common goal, saving time and effort while 
increasing quality. Now I&#39;d like to dig into the details of &lt;i&gt;how &lt;/i&gt;to write good Acceptance Criteria.&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;reader-article-content&quot; dir=&quot;ltr&quot;&gt; 
  &lt;h2&gt;Behaviour Driven vs Procedural Driven Mindsets&lt;/h2&gt; 
  &lt;p&gt;Many of us may be used to writing/seeing procedural driven tests; 
step by step instructions with actions and expected results. 
Procedure-driven&amp;nbsp;tests are often &lt;i&gt;imperative&lt;/i&gt; and trace a path 
through the system that covers multiple behaviors. As a result, they&amp;nbsp;may
 be unnecessarily long, which can delay failure investigation, increase 
maintenance costs, and create confusion.&lt;/p&gt; 
  &lt;p&gt;Acceptance criteria, and indeed Behaviour Driven tests, should instead be behaviour driven.&lt;/p&gt; 
  &lt;p&gt;This means they should be &lt;i&gt;Declarative&lt;/i&gt;, specifying how a system should behave in a particular scenario.&lt;/p&gt; 
  &lt;p&gt;&lt;b&gt;Procedural/Imperative:&lt;/b&gt;&lt;/p&gt; 
  &lt;pre spellcheck=&quot;false&quot;&gt;Given the user opens a web browser
&lt;span class=&quot;hljs-keyword&quot;&gt;And&lt;/span&gt; the user navigates to &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://localhost/mysite/&quot;&lt;/span&gt;
&lt;/pre&gt; 
  &lt;p&gt;&lt;b&gt;Behaviour Driven/Declarative:&lt;/b&gt;&lt;/p&gt; 
  &lt;pre spellcheck=&quot;false&quot;&gt;Given a web browser is at the &lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt; home page
&lt;/pre&gt; 
  &lt;p&gt;As a result of this declarative mindset, a behaviour should have a &lt;b&gt;one to one relationship with scenarios&lt;/b&gt;,
 meaning we don&#39;t have multiple expectations of behaviour from a single 
scenario, which would be easy to do with the procedural mindset:&lt;/p&gt; 
  &lt;pre spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;hljs-regexp&quot;&gt;//&lt;/span&gt; BAD EXAMPLE - covers &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; scenarios

When the user enters &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt; into the search bar
Then links related to &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt; are shown &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt; the results page
When the user clicks &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt; the &lt;span class=&quot;hljs-string&quot;&gt;&quot;Images&quot;&lt;/span&gt; link at the top &lt;span class=&quot;hljs-keyword&quot;&gt;of&lt;/span&gt; the results page
Then images related to &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt; are shown &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt; the results page
&lt;/pre&gt; 
  &lt;h2&gt;Given, When Then&lt;/h2&gt; 
  &lt;p&gt;Acceptance Criteria should be written in the Given, When Then 
format. The reason for this is that each of these steps has a specific 
purpose. Respect the order of these, if you move them around, the 
criteria may not be clear.&lt;/p&gt; 
  &lt;h3&gt;&lt;b&gt;Given&lt;/b&gt;&lt;/h3&gt; 
  &lt;p&gt;Given defines the prerequisites for the scenario, which screen we are on, and which data already exists. As it sets up &lt;i&gt;state&lt;/i&gt;, it should be written in the &lt;b&gt;present perfect&lt;/b&gt; tense, eg:&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Bad&lt;/i&gt;: Given the Administrator navigates to the User Search page&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Good:&lt;/i&gt; Given the Administrator is on the User Search page&lt;/p&gt; 
  &lt;h3&gt;&lt;b&gt;When&lt;/b&gt;&lt;/h3&gt; 
  &lt;p&gt;When indicates the action being performed. It should therefore be written in the &lt;b&gt;present&lt;/b&gt; tense, eg:&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Bad:&lt;/i&gt; When the Administrator filtered the Users by name &quot;Smith&quot;&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Good:&lt;/i&gt; When the Administrator filters the Users by name &quot;Smith&quot;&lt;/p&gt; 
  &lt;h3&gt;&lt;b&gt;Then&lt;/b&gt;&lt;/h3&gt; 
  &lt;p&gt;Then is the assertion, it verifies the new state that is a result of the When action.These are better written in the &lt;b&gt;present&lt;/b&gt; tense, because using the future tense reinforces a procedure driven approach, treating the scenario as a time sequence.&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Bad:&lt;/i&gt;&amp;nbsp;Then users containing the name &quot;Smith&quot; will be shown on the results page&lt;/p&gt; 
  &lt;p&gt;&lt;i&gt;Good:&lt;/i&gt; Then users containing the name &quot;Smith&quot; are shown on the results page&lt;/p&gt; 
  &lt;h2&gt;Write full sentences&lt;/h2&gt; 
  &lt;h3&gt;Subject - Predicate - Action&lt;/h3&gt; 
  &lt;p&gt;It may tempting to leave parts of speech out of a step line for 
brevity, especially when using Ands and Buts, but partial phrases make 
steps ambiguous. For example, consider the following:&lt;/p&gt; 
  &lt;pre spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Bad Example &lt;/span&gt;

Given the user navigates to the Google home page
When the user entered &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt; at the search bar
Then the results page shows links related to &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;And&lt;/span&gt; image links &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;And&lt;/span&gt; video links &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;cats&quot;&lt;/span&gt;
&lt;/pre&gt; 
  &lt;p&gt;Writing steps without a clear subject and predicate is not only poor English but poor communication.&lt;/p&gt; 
  &lt;h2&gt;Test Cases&lt;/h2&gt; 
  &lt;p&gt;Acceptance Criteria should cover the main scenarios which will be faced by the new functionality. They are &lt;i&gt;not &lt;/i&gt;a
 full breakdown of test cases. Developers writing unit tests can cover 
edge cases and paths through the code, while QA can apply a broader, 
more exploratory approach to the new feature. &lt;/p&gt; 
  &lt;p&gt;If you find yourself creating lots of different Acceptance Criteria, it might mean that the job needs to be broken down. &lt;/p&gt; 
  &lt;h2&gt;Summary&lt;/h2&gt; 
  &lt;p&gt;The Given, When, Then format may seem verbose, and all this talk of
 correct grammar might sound scary, but writing Acceptance Criteria this
 way is quite easy. Think of each Acceptance Criteria as an &lt;b&gt;action &lt;/b&gt;with an &lt;b&gt;expected result&lt;/b&gt; - and then add &lt;b&gt;prerequisites &lt;/b&gt;(the &quot;Given&quot;) only if required. &lt;/p&gt; 
  &lt;p&gt;Use of the correct tenses is something that just comes with 
practice and is not super important, it just helps to prevent you 
falling back into the procedural mindset. It&#39;s more important to write 
full sentences and follow the Given/When/Then, or 
Prerequisites/Action/Expectation format.&lt;/p&gt; 
  &lt;p&gt;Following this format sets a standard which all jobs can follow, 
bringing consistency and clarity to tasks. It ensures that the required 
expectations are met, and gets the team thinking about all the actions 
that need to be performed. &lt;/p&gt;
 
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/2578901688538175598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2021/10/writing-good-acceptance-criteria.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/2578901688538175598'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/2578901688538175598'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2021/10/writing-good-acceptance-criteria.html' title='Writing Good Acceptance Criteria'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-cAVerkoxjGs/YUvH5K4gaPI/AAAAAAABQQg/Z1anZbziFVsPbC9k5jPub24S4DMBwMnuwCLcBGAsYHQ/s72-w640-h388-c/1532986745531.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-9045329949221482060</id><published>2021-09-24T15:10:00.009+00:00</published><updated>2022-09-12T13:20:00.905+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Gaming"/><category scheme="http://www.blogger.com/atom/ns#" term="technology"/><title type='text'>What&#39;s the best gaming controller?</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-anxXyloVJJc/YU3orm-GxcI/AAAAAAABQUU/Bwb_ihurHh8wad-7BkYoD2niX5zINDa1QCLcBGAsYHQ/s730/Screenshot%2B2021-09-25%2B010220.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Game controller&quot; border=&quot;0&quot; data-original-height=&quot;385&quot; data-original-width=&quot;730&quot; height=&quot;338&quot; src=&quot;https://1.bp.blogspot.com/-anxXyloVJJc/YU3orm-GxcI/AAAAAAABQUU/Bwb_ihurHh8wad-7BkYoD2niX5zINDa1QCLcBGAsYHQ/w640-h338/Screenshot%2B2021-09-25%2B010220.png&quot; title=&quot;A controller I designed in the mid 90s&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;I&#39;ve tried all the game controllers. They all have such major pros and cons. If someone could put all the good features into one controller, it would be amazing.&lt;p&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Xbox&lt;/h2&gt;&lt;p&gt;I owned &lt;a href=&quot;https://xbox.fandom.com/wiki/The_Duke&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;the Duke&lt;/a&gt;, and I didn&#39;t mind it, but I have decent sized hands and it still felt like a bowl with buttons so when they brought out the newer controller I felt it was a good move. Ever since then Xbox controllers have been the most natural, comfortable controller out there, without question. I had a 360 controller for over a decade and a half across the Xbox 360 and PC, and it just worked.&amp;nbsp;&lt;/p&gt;&lt;p&gt;I love the concave thumbsticks, I&#39;m cool with the offset sticks, the buttons have always felt solid and the triggers get smoother with every release. It&#39;s a solid controller in every way, the D-pad on the new Series S controller is clicky but robust, the whole thing is comfortable and high quality. I love the Xbox controllers. They are now, however, missing some significant features.&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Switch&lt;/h2&gt;&lt;p&gt;What can I say. They are clunky, laggy, and overpriced, but you have to love them. It&#39;s the compromises that makes the Switch so charming, and you really can&#39;t compain about the joycons given what they contribute to the Switch&#39;s portability. It&#39;s a shame that the motion sensors are so underused.&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Switch Pro&lt;/h3&gt;&lt;p&gt;It just can&#39;t compete with the Xbox and Playstation and doesn&#39;t even want to try. It&#39;s much better than the the joycon but it&#39;s still just a cheap Xbox imitation.&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;PS5 Dualsense&lt;/h2&gt;&lt;p&gt;I was always a fan of the Playstation controllers
 and enjoyed their skinny form. The PS5 controller however is a little 
bulky and it surprised me that they would do that after 4 generations of
 the skinny form factor. It&#39;s not the worst thing in the world but I did
 find myself distracted by its thickness from time to time.&lt;/p&gt;&lt;p&gt;My 
other major complaint with the Playstation controllers, and it&#39;s a big 
one, is the convex thumbsticks. I don&#39;t know if it&#39;s the material or 
just because I sweat 😅 but I found myself slipping off them often, 
frequently causing me issues in game. No such issues with the concave Xbox thumbsticks.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A minor but significant 
complaint is the positioning of the D pad. I realise this is a long 
standing Playstation custom, but the reality is, in this day and age, 
the D pad feels out of place where it is, because it&#39;s something that&#39;s 
no longer significant in games. Maybe it&#39;s just me and my 15 years 
playing with an Xbox controller, but hey, Nintendo (the makers of the 
centre stick N64 controller) decided to follow Xbox for a reason.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;However,
 the innovation in the Dualsense is unmatched. Playing Astro&#39;s Playroom 
was one of the most significant moments in my gaming life - because of 
this controller. And it&#39;s not just the tactile triggers, which are 
absolute game changers in the world of gaming controllers, but also the 
sound, light and vibration which all genuinely add to the immersion of 
the game, setting this controller far ahead of all the rest. No other 
controller out there uses the sound and light to such immersive effect.&lt;/p&gt;&lt;p&gt;It also has a touchpad, and motion sense. It&#39;s the one controller with absolutely everything.&lt;/p&gt;&lt;p&gt;I really think that more time needs to be spent talking about those 
triggers. The way that they tense up, and then release, and how that 
adds to the immersion, is an absolute joy. Maybe 
because its paired with some vibration and joypad sound, I&#39;m not sure, 
but they make the game seem more &lt;i&gt;real&lt;/i&gt;, more physical.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you 
haven&#39;t tried the Dualsense triggers, you are missing out on a whole other dimension of 
gaming. I&#39;m sure the other controllers will copy this feature soon. 
Until then, the PS5 will have a huge advantage.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/9045329949221482060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2021/09/whats-best-gaming-controller.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9045329949221482060'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9045329949221482060'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2021/09/whats-best-gaming-controller.html' title='What&#39;s the best gaming controller?'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-anxXyloVJJc/YU3orm-GxcI/AAAAAAABQUU/Bwb_ihurHh8wad-7BkYoD2niX5zINDa1QCLcBGAsYHQ/s72-w640-h338-c/Screenshot%2B2021-09-25%2B010220.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-2676407596772376645</id><published>2021-09-23T06:57:00.007+00:00</published><updated>2022-03-25T00:27:40.716+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Acceptance Critiera"/><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><category scheme="http://www.blogger.com/atom/ns#" term="Product Owner"/><title type='text'>The Importance of Good Acceptance Criteria</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-bJEyb5Rkg4I/YUvHewAd0bI/AAAAAAABQQc/85qqTsb_5g4c1ver_HpPIFdvOEq6VvjZgCPcBGAYYCw/s840/1532322467593.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;720&quot; data-original-width=&quot;840&quot; height=&quot;548&quot; src=&quot;https://1.bp.blogspot.com/-bJEyb5Rkg4I/YUvHewAd0bI/AAAAAAABQQc/85qqTsb_5g4c1ver_HpPIFdvOEq6VvjZgCPcBGAYYCw/w640-h548/1532322467593.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;reader-article-content&quot; dir=&quot;ltr&quot;&gt;&lt;p&gt;Acceptance Criteria can be seen as a chore, a convoluted, verbose set of prose with the sole 
purpose of satisfying &quot;the business&quot;. At best, its value is 
underestimated and it is often written as a vague list of requirements.&lt;/p&gt; 
  &lt;p&gt;Given the right attention, Acceptance Criteria can be extremely 
valuable to all members of a Scrum team. Before it can be done 
correctly, we have to understand its value.&lt;/p&gt; 
  &lt;p&gt;So what exactly is the point of Acceptance Criteria?&lt;/p&gt; 
  &lt;h2&gt;Purpose of Acceptance Criteria&lt;/h2&gt; 
  &lt;h3&gt;To define boundaries&lt;/h3&gt; 
  &lt;p&gt;Acceptance criteria help development teams define the boundaries of
 a user story. In other words, acceptance criteria help you confirm when
 the application functions as desired.&lt;/p&gt; 
  &lt;h3&gt;To reach consensus&lt;/h3&gt; 
  &lt;p&gt;Having acceptance criteria synchronises the development team with 
the client. The team knows exactly what conditions should be met, just 
as the client knows exactly what to expect from the developed 
functionality.&lt;/p&gt; 
  &lt;h3&gt;To allow for accurate planning and estimation&lt;/h3&gt; 
  &lt;p&gt;Acceptance criteria scenarios allow for the correct division of 
user stories into tasks so user stories are correctly estimated and 
planned.&lt;/p&gt; 
  &lt;h3&gt;To serve as a basis for tests&lt;/h3&gt; 
  &lt;p&gt;Acceptance criteria provide a good baseline for writing tests. Test
 cases can break down Acceptance Criteria to go into more functional 
detail, and to cover edge cases.&lt;/p&gt; 
  &lt;h2&gt;Acceptance Criteria helps the team deliver quality&lt;/h2&gt; 
  &lt;p&gt;Acceptance Criteria is vital for delivering quality. If done 
correctly, it can simplify development and guide a comprehensive testing
 strategy. It is the glue that holds requirements together.&lt;/p&gt; 
  &lt;p&gt;Acceptance Criteria is valuable to all stakeholders; Developers, 
QA, Product Owners, and the team as a whole. How it helps each 
stakeholder, however, varies according to their role.&lt;/p&gt; 
  &lt;h2&gt;Good Acceptance Criteria&lt;/h2&gt; 
  &lt;h3&gt;How it benefits Developers&lt;/h3&gt; 
  &lt;p&gt;Good Acceptance Criteria gives developers clarity and allows them 
to break down their tasks into manageable pieces of functionality. With 
visibility of all possible scenarios, good Acceptance Criteria actually 
allows optimum design of the code. It enables developers to structure 
their code in a way that best meets the requirements. The code can be 
written around each scenario, ensuring each criteria is met in the 
simplest way possible.&lt;/p&gt; 
  &lt;p&gt;The clarity given by good Acceptance Criteria keeps the business 
requirements at the forefront of the developer&#39;s mind, helping them to 
avoid getting bogged down in technical details which may not be 
conducive to the task.&lt;/p&gt; 
  &lt;h3&gt;How it benefits QA&lt;/h3&gt; 
  &lt;p&gt;Good Acceptance Criteria can guide QA in generating test cases and 
any required test data. With clear, simple scenarios, QA will have a 
solid base for test cases, and can then focus on expanding the 
Acceptance Criteria to cover edge cases.&lt;/p&gt; 
  &lt;p&gt;Without clear, broken down Acceptance Criteria, it can be hard to 
work out test cases. If this happens, certain scenarios might be missed,
 and the important expectations of the job might be overlooked.&lt;/p&gt; 
  &lt;h3&gt;How it benefits the team&lt;/h3&gt; 
  &lt;p&gt;Good Acceptance Criteria helps get all the team on the same page. 
It aligns everyone with common goals, and helps them work together to 
build out the requirements. This collaboration is important and often 
overlooked.&lt;/p&gt; 
  &lt;p&gt;Development and QA can come together at the start of a task in 
order to work out what needs to be tested. This allows Development to 
perform some degree of Test Driven Development. Even if it isn&#39;t 
possible to write automated tests before the code, the developer will at
 least have a good idea of what those tests are going to be before 
writing any code.&lt;/p&gt; 
  &lt;p&gt;QA can guide this process, elaborating on what they will be 
testing, helping to set up test data, and informing the developer of 
possible edge cases to watch out for.&lt;/p&gt; 
  &lt;p&gt;If the Acceptance Criteria is missing anything, the Product Owner 
can be questioned for more details before the work commences. Without 
clear Acceptance Criteria, there is no way of knowing if there are any 
missing details.&lt;/p&gt; 
  &lt;h2&gt;Good Acceptance Criteria can make a difference&lt;/h2&gt; 
  &lt;p&gt;With good Acceptance Criteria, the team is able to see, at a 
glance, what is required from a task. It provides a consensus for the 
whole team which aids both planning and delivery.&lt;/p&gt; 
  &lt;p&gt;Good Acceptance Criteria helps developers come up with cleaner 
code. It makes testers&#39; lives much easier. It helps the team come up 
with the best Automated Testing solutions, which is vital for Agile 
projects. It helps the team plan the best possible approach, and avoids 
stumbling into questions mid-development.&lt;/p&gt; 
  &lt;p&gt;Don&#39;t underestimate the value of good Acceptance Criteria. It can increase productivity, collaboration, and quality.&lt;/p&gt;
 
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/2676407596772376645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2021/09/the-importance-of-good-acceptance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/2676407596772376645'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/2676407596772376645'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2021/09/the-importance-of-good-acceptance.html' title='The Importance of Good Acceptance Criteria'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-bJEyb5Rkg4I/YUvHewAd0bI/AAAAAAABQQc/85qqTsb_5g4c1ver_HpPIFdvOEq6VvjZgCPcBGAYYCw/s72-w640-h548-c/1532322467593.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-4810062468603718278</id><published>2021-02-16T11:34:00.003+00:00</published><updated>2022-03-25T00:27:48.879+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><title type='text'>In Coding, Nothing is Trivial</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-bEe4-ROL0jw/YCurlfIuNgI/AAAAAAABMq0/tnmsgcMDq3wu5OotIaEjMWxklIqZsVv8wCLcBGAsYHQ/s864/office-mess-paper-hand-help_blog-size.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;571&quot; data-original-width=&quot;864&quot; height=&quot;422&quot; src=&quot;https://1.bp.blogspot.com/-bEe4-ROL0jw/YCurlfIuNgI/AAAAAAABMq0/tnmsgcMDq3wu5OotIaEjMWxklIqZsVv8wCLcBGAsYHQ/w640-h422/office-mess-paper-hand-help_blog-size.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Imagine you&#39;re reviewing some code, as part of a Pull Request, and the developer has misspelt a variable. Or added a magic string instead of a constant. Or put the expected/actual parameters in an assertion the wrong way around (although it kinda doesn&#39;t matter because they&#39;re the same)? &lt;/p&gt;&lt;p&gt;You can politely comment on it, and perhaps they will fix it up. But sometimes you might be met with resistance.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&quot;It&#39;s not that important.&quot;&lt;/p&gt;&lt;p&gt;To a degree, they&#39;re right. These are pretty trivial observations. There are probably bigger things to address, such as the logic, the architecture, the test coverage etc.&amp;nbsp;&lt;/p&gt;&lt;p&gt;However, in coding, these trivial issues tend to come back to bite you, either as bugs, or as maintenance headaches. &lt;/p&gt;&lt;p&gt;You don&#39;t want to nag people. You don&#39;t want to become a &quot;clean code nazi&quot;. But you can firmly assert that you think a mistake is being made and that a potential issue could arise.&amp;nbsp;&lt;/p&gt;&lt;p&gt;There are some things in coding that are a personal preference. There are some things that are virtually (though not completely) insignificant and which you should avoid fighting about (tabs vs spaces) and then there are things which actually matter. The lines are blurred and you should always be pragmatic - but the things which actually matter can be proven to matter - a misnamed variable can cause confusion, expected/actual parameters the wrong way around can lead to false positives in your tests, and magic strings can lead to runtime errors, code duplication, and mysterious bugs that can really mess up your day.&lt;/p&gt;&lt;p&gt;What&#39;s important is that you communicate these issues when making your suggestions. Make it clear that this isn&#39;t a personal preference thing - it&#39;s not you being fussy, but that it could lead to genuine problems.&amp;nbsp; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;The main reason that many of these &quot;trivial&quot; issues can lead to serious problems is maintainability - other developers working on the code.&amp;nbsp; Maintainability is just so important - not having it leads to bugs, slow development, demoralised developers and more. Anything that affects maintainability, isn&#39;t trivial. Its effects are amplified because of all the people that become involved in the problem.&lt;/p&gt;&lt;p&gt;When you have maintainability problems, you get bugs. It doesn&#39;t take much to turn a badly named variable into a half day investigation and a costly Production change.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, raise your standards. Don&#39;t settle for &quot;It&#39;s not that 
important&quot;. If you have an issue with it, if it niggles at your brain 
even slightly, it&#39;s for a good reason. Your subconcious can spot a time 
bomb. Trust it.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/4810062468603718278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2021/02/in-coding-nothing-is-trivial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4810062468603718278'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4810062468603718278'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2021/02/in-coding-nothing-is-trivial.html' title='In Coding, Nothing is Trivial'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-bEe4-ROL0jw/YCurlfIuNgI/AAAAAAABMq0/tnmsgcMDq3wu5OotIaEjMWxklIqZsVv8wCLcBGAsYHQ/s72-w640-h422-c/office-mess-paper-hand-help_blog-size.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-7472497140819312729</id><published>2020-11-24T00:56:00.006+00:00</published><updated>2022-03-25T00:27:56.404+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Acceptance Critiera"/><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Writing Good Acceptance Tests</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-pc4PegArb_M/X7xaH3OVLJI/AAAAAAABLR8/8mjKYges82wtBXmgwyxEZBIxjGOld-e5gCLcBGAsYHQ/s1080/1537752044154.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;675&quot; data-original-width=&quot;1080&quot; height=&quot;400&quot; src=&quot;https://1.bp.blogspot.com/-pc4PegArb_M/X7xaH3OVLJI/AAAAAAABLR8/8mjKYges82wtBXmgwyxEZBIxjGOld-e5gCLcBGAsYHQ/w640-h400/1537752044154.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Acceptance tests can be used to verify end to end functionality in a way that is understandable to the business. They are very broad compared with unit tests, and when automated via a tool like Specflow, are based on a more natural language. It&#39;s important that we use this natural language to keep tests simple and concise, rather than trying to write long-winded &quot;functional&quot; tests.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Good Gherkin&lt;/h1&gt;Before writing Acceptance tests, learn about &lt;a href=&quot;https://www.linkedin.com/pulse/writing-good-acceptance-criteria-stuart-dobson/&quot;&gt;Acceptance Criteria Best Practices&lt;/a&gt;. The ability to write good Acceptance Criteria translates directly to Acceptance testing. They both follow the same standards and they can be written in the same way.&lt;br /&gt;&lt;br /&gt;We should attempt to apply these best practices apply to Acceptance tests as much as is practically possible, especially when it comes to grammar as this helps us stick to a standard.&lt;br /&gt;&lt;br /&gt;The most important thing is to remember that Acceptance tests should be written with the Given, When, Then syntax where:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Given sets up a state,&lt;/li&gt;&lt;li&gt;When is an action,&lt;/li&gt;&lt;li&gt;Then is an assertion. &lt;/li&gt;&lt;/ul&gt;Every test should have an action and an assertion, and most require some kind of prerequisites. This ensures that the outcome of actions are actually being tested, and maps directly to a test case.&lt;br /&gt;&lt;br /&gt;Let&#39;s reiterate a couple of points.&lt;br /&gt;&lt;br /&gt;Given should be used to set up pre-requisites. It should not be used for actions, for example &quot;Given I navigate to the admin page&quot;. You can however say &quot;Given I am on the admin page&quot; which achieves the same thing but keeps the structure clearer.&lt;br /&gt;&lt;br /&gt;Likewise, Then should not be used for actions, such as &quot;Then I delete a record&quot;. Then is for assertions, for checking the state of something that was changed by the &quot;When&quot; directive.&lt;br /&gt;&lt;br /&gt;Remember to be careful when using AND that you don&#39;t break these rules. For example, don&#39;t say&lt;br /&gt;&lt;br /&gt;&quot;WHEN I delete a record THEN I should have a record AND I click exit&quot;&lt;br /&gt;&lt;br /&gt;In this case, the AND is now a &quot;When&quot;, not a &quot;Then&quot;. In other words, AND should be the same as the preceding directive. In the above example, as it is not an assertion, it should be a &quot;When&quot;, and you probably want to follow it with another assertion &quot;Then&quot;.&lt;br /&gt;&lt;br /&gt;It might sound like I&#39;m picking on grammar here but the point is that the 3 directives serve different purposes - the point of a test is to ensure that an action has an outcome. Mixing up their use means that you may not be creating an actual test case, but rather running through a series of steps, and you may not even have any assertions.&lt;br /&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Focus on business actions rather than functional sequences&lt;/h1&gt;Practically speaking, in many Acceptance tests there are usually a lot of When steps, or actions performed. However, where possible we should strive to make all End to End code as concise as possible. Writing Specflow/Cypress that does several steps on one line is OK if each of those steps make up a single functional action. &lt;br /&gt;&lt;br /&gt;For example, rather than&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;When I populate the form with the following values:
 | Field | Value |
And I click the &quot;Save Changes&quot; button
&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We could just say&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;When I save the following values:| Field | Value |
&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and have the underlying code also click the save button/save the changes. &lt;br /&gt;&lt;br /&gt;The best way to think about this is we should be more concerned with business actions, or feature functionality, than stepping through a sequence of button clicks.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Avoid multiple When/Then repetitions&lt;/h1&gt;One test, one behaviour, where possible. Any more and you&#39;re really testing multiple criteria, and each test should be testing one scenario (hence the Specflow keyword &quot;Scenario&quot;). &lt;br /&gt;&lt;br /&gt;Of course with Acceptance tests having such a high overhead, you might still want to do multiple assertions from time to time, but use it sparingly and be aware of it.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Use Background steps&lt;/h1&gt;A background step happens before every Scenario in a feature file. Use it for setting up data. Then your tests can be clean and start with a simple &quot;Given I am on the Search screen&quot;.&lt;br /&gt;&lt;br /&gt;If you need each scenario to have different data you can put the data setup Given steps in each test, but in this case you might want to consider why there is different data for each test, and perhaps you need to move the tests into a different feature file.&lt;br /&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Avoid testing logic&lt;/h1&gt;It can be tempting to test lots of different scenarios with Acceptance tests. I am speaking from extensive experience when I say: this will make your life very difficult. Acceptance tests have high overhead and can be extremely flaky.&lt;br /&gt;&lt;br /&gt;Acceptance tests are for testing high level End to End functionality. They should &lt;b&gt;not &lt;/b&gt;be used for testing intricate business logic. This should be done by Unit and Integration tests.&lt;br /&gt;&lt;br /&gt;If it is too hard to write Unit/Integration tests, you may need to look at making your code more testable and addressing technical debt.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A large part of avoiding testing the logic comes down to &lt;a href=&quot;https://techbeacon.com/devops/joe-colantonio-how-get-testers-developers-working-together&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;testers and developers working together&lt;/a&gt;. When this happens, you can avoid a situation where the testers may write a dozen Acceptance tests which just test the same code path with different variables - not valuable from a quality perspective and also adding a huge unnecessary overhead to the testing time and maintenance.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When working together, developers and testers can come up with a strategy where the logic and edge cases are covered by unit/integration tests, while the basic Acceptance Criteria/end to end connectivity/functionality can be verified by a small number of Acceptance tests.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;Don&#39;t write too many Acceptance tests&lt;/h1&gt;Acceptance tests are known for being flaky and unreliable. They can also be hard to maintain. Keeping the number of tests low makes them easier to manage.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Acceptance tests can provide tremendous value by verifying End to End functionality, but people need to be able to trust them, so keeping them easy to maintain is key to keeping them reliable.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/7472497140819312729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2020/11/writing-good-acceptance-tests.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/7472497140819312729'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/7472497140819312729'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2020/11/writing-good-acceptance-tests.html' title='Writing Good Acceptance Tests'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-pc4PegArb_M/X7xaH3OVLJI/AAAAAAABLR8/8mjKYges82wtBXmgwyxEZBIxjGOld-e5gCLcBGAsYHQ/s72-w640-h400-c/1537752044154.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-725227606966879503</id><published>2019-05-08T05:56:00.005+00:00</published><updated>2022-03-25T00:28:12.567+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><category scheme="http://www.blogger.com/atom/ns#" term="Object Oriented Programming"/><category scheme="http://www.blogger.com/atom/ns#" term="SOLID"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Technical Debt"/><title type='text'>Clean coding Tips: Access Modifiers</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-TKcU_oIhPj4/YUvG8U66C6I/AAAAAAABQQU/WoLFlPaqSto6QEuv3OmEHmO3Zq04hoUkQCPcBGAYYCw/s557/R.f1542243e06c93af3cc45655692bd856.png&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;429&quot; data-original-width=&quot;557&quot; height=&quot;308&quot; src=&quot;https://1.bp.blogspot.com/-TKcU_oIhPj4/YUvG8U66C6I/AAAAAAABQQU/WoLFlPaqSto6QEuv3OmEHmO3Zq04hoUkQCPcBGAYYCw/w400-h308/R.f1542243e06c93af3cc45655692bd856.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;It seems to be by default that classes, methods, etc are created with the public access modifier.&lt;br /&gt;&lt;br /&gt;This is not actually the case, the default is internal class/private members, but public seems to be the de-facto choice by a lot of developers.&lt;br /&gt;&lt;br /&gt;If you&#39;re creating a public class - you have a big responsibility. Your code can now be used by anything else in the application, or even outside it. This means if you change the internal working of it, you will affect everything that uses it - and you have no control over what that is. This means a couple of things. &lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Naming is always super important&lt;/h3&gt;
&lt;p&gt;
Naming of public classes and methods and their expectations should be crystal clear. Don&#39;t rely on comments to convey intentions. It must be highly obvious what the class is for, what it does, and how method parameters are used. It should be specific and adhere to the Single Responsibility Principle - one reason to change. If someone comes along and adds a parameter to one of your methods to get it to do something else, this is an indication that the class&#39;s purpose was not clear enough.&lt;br /&gt;&lt;br /&gt;If the naming is not clear, the purpose gets diluted, and the class will be modified away from its original intentions. This causes code to bloat and become more prone to bugs. &lt;br /&gt;&lt;br /&gt;Tip: This is yet another reason to avoid &quot;generic static helpers&quot;!
If your classes or methods are public, tests need to cover every possible way that the code can be used - every single path. What this means is that anyone using the code will know exactly what is expected of it because its functionality is documented by tests. Any usage of the code will already be covered by a test.&lt;br /&gt;&lt;br /&gt;If you don&#39;t create tests, anyone can come along and change this code which can then affect any number of consumers.
&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
Don&#39;t make life hard for yourself&lt;/h3&gt;
&lt;p&gt;
Don&#39;t want this responsibility? Simple: Don&#39;t make your classes and methods public. Of course internal members should always be tested and code should be named well. But these issues take on less importance if the code is isolated.&lt;br /&gt;&lt;br /&gt;Go with the lowest access first and only open it up as and when you need to, When you do open it up, make sure that it does what it says it will, and it is fully tested. The important thing to remember is that when a class is public, it increases its exposure, which allows it to be coupled with more code. This is a significant cause of spaghetti code and regression issues as the code is maintained.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;
Keep code restricted to where it is needed. If it needs to be public, it needs to be robust.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/725227606966879503'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/725227606966879503'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2019/05/clean-coding-tips-isolation.html' title='Clean coding Tips: Access Modifiers'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-TKcU_oIhPj4/YUvG8U66C6I/AAAAAAABQQU/WoLFlPaqSto6QEuv3OmEHmO3Zq04hoUkQCPcBGAYYCw/s72-w400-h308-c/R.f1542243e06c93af3cc45655692bd856.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-8299694557386614367</id><published>2018-10-05T12:55:00.003+00:00</published><updated>2022-03-25T00:28:22.516+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Code Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><title type='text'>Why should I care about Quality? I&#39;m a developer!</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-f1dsSIx4YDM/X4WW3UyXkqI/AAAAAAABKX0/N-rIo3FPyqwUB9FsVXS1ra9kvzoixcMFQCLcBGAsYHQ/s960/quality.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;720&quot; data-original-width=&quot;960&quot; height=&quot;480&quot; src=&quot;https://1.bp.blogspot.com/-f1dsSIx4YDM/X4WW3UyXkqI/AAAAAAABKX0/N-rIo3FPyqwUB9FsVXS1ra9kvzoixcMFQCLcBGAsYHQ/w640-h480/quality.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;OK, no developer wants to create bad quality code. But for most developers, quality is seen as something separate from development, something that is checked after the work has been done. It is something that QA do, after you throw your code over the fence. Thinking about quality at during development is a burden, slowing down the creation of functionality, holding up new features. Thinking about quality before development, well that&#39;s just crazy talk.&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;

Old Habits Die Hard
&lt;/h3&gt;&lt;p&gt;
In the Agile world, this is starting to change. Quality is being baked into the development process and there is more interaction between development and QA during the development phase. At least, that&#39;s the theory. In practice, we often slip back into bad habits of throwing code over the fence.
&lt;/p&gt;
&lt;p&gt;
The reason we keep falling back into bad habits is because the attitude around quality is the same as it always was. It is still seen as something separate from development, separate from design, separate from planning. This causes it to be seen as a burden - extra work that just has to be done.
&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;
Quality as the Glue
&lt;/h3&gt;&lt;p&gt;
If instead we change our perspective, and try to see Quality as an integral part of the entire development process, it can change the way we all work, from developers to product owners. Instead of a burden, quality should be a thread that runs throughout the process, and actually defines how all work is done from the ground up. If this is done, it can actually simplify and speed up development.
&lt;/p&gt;
Baking quality into your process shifts the responsibility to everyone, rather than just QA. Having the whole team (including product owners) take responsibility for quality sets the focus around Acceptance Criteria. This &quot;requirements-centric&quot; approach gets everyone thinking about quality right from the refinement meeting. When the entire team comes together and builds good Acceptance Criteria, quality becomes a natural, and welcome, part of the development process.
&lt;p&gt;
Several things then happen. First, the whole team are forced to agree on the details of the requirements before development starts. Before any technical decisions or implementation planning, the exact requirements are clarified. Only by making this an imperative part of the process (usually the refinement meeting) can this happen effectively.
&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;
Good Acceptance Criteria Drives Good Development
&lt;/h3&gt;&lt;p&gt;
With clear Acceptance Criteria, development is simplified. Development knows exactly what they need to implement, and when they know this, the process of writing automated tests is no longer abstract and difficult. Test Driven Development is a tricky thing to do, in practice. However, with clear goals, a developer can start with &quot;pseudo tests&quot; - tests which are just code comments - but which outline the business logic before coding begins. These will be a granular list of Prerequisite/Action/Assertions - Unit tests, essentially - outlining the required logic. Then, development becomes a process of implementing that logic.
&lt;/p&gt;
&lt;p&gt;
Breaking the logic down before development begins is a very effective way of ensuring that clean code practices, especially the Single Responsibility Principle, are followed. It becomes natural to keep the logic simple, concise, and separated from other concerns, such as infrastructure. It encourages clean Object Orientated design.
&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;
Good Acceptance Criteria Drives Good QA
&lt;/h3&gt;&lt;p&gt;
Also QA know exactly what they will be getting. They know what parts of the job will be automated, so they can design better integration, acceptance, and End to End tests, as well as an effective exploratory strategy.
&lt;/p&gt;
&lt;p&gt;
Without this clarity, QA are left with waiting until a job is done and not knowing what they&#39;re going to get - which is a recipe for annoying manual regression testing, and no doubt, bugs.
&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;
Agile Demands Quality, Quality Brings Clarity
&lt;/h3&gt;&lt;p&gt;
Agile is about iterating fast. You cannot do this when QA are held back by a requirement to constantly manually regression test, or worse still, you avoid regression testing and hope new development doesn&#39;t break anything.
&lt;/p&gt;
&lt;p&gt;
With good Acceptance Criteria baked into the process, everyone has clarity. As a developer, this makes your life so much easier. You know what needs to be developed before you start, which allows you to concentrate on technical implementation details. With clear requirements, the code is cleaner, so development and maintenance is easier. This allows the team to iterate fast, able to add new features quickly.
&lt;/p&gt;
&lt;p&gt;
Early automated testing becomes a breeze, and with this automation in place, QA can focus on exploration. With automation, we are able to develop with confidence, and innovate freely.
&lt;/p&gt;
&lt;p&gt;
Quality no longer slows down the development process, but &lt;i&gt;guides &lt;/i&gt;it.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;
That&#39;s&lt;/b&gt; why developers should care about quality.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/8299694557386614367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2018/10/why-should-i-care-about-quality-im.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/8299694557386614367'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/8299694557386614367'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2018/10/why-should-i-care-about-quality-im.html' title='Why should I care about Quality? I&#39;m a developer!'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-f1dsSIx4YDM/X4WW3UyXkqI/AAAAAAABKX0/N-rIo3FPyqwUB9FsVXS1ra9kvzoixcMFQCLcBGAsYHQ/s72-w640-h480-c/quality.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-4751892421348729985</id><published>2018-04-08T22:03:00.024+00:00</published><updated>2021-02-16T10:47:49.603+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clean code"/><title type='text'>Being a Senior Developer is more than being a long serving developer</title><content type='html'>&lt;p&gt;Like many people, I started my development career from another role. I 
taught myself coding and then built software to help the business and 
myself. It was well received, but I did not feel like a &quot;real&quot; developer
 yet.&lt;br /&gt;
&lt;br /&gt;
This experience convinced me that software was what I 
wanted to do, so I looked for a junior developer role. This wasn&#39;t easy,
 most companies want people who can come in and start being productive 
right away, and there were many skills I lacked from not working in 
a &quot;true&quot; software development environment. Eventually, after much persistence, I was taken in as a
 junior developer for a large finance company.&lt;br /&gt;
&lt;br /&gt;
When handing in my resignation to my non-dev-shop company, I was offered a
pay rise to more than I would be getting in the new role at the finance company. I was 
also offered a new position, the position of &quot;Senior&quot; developer. &lt;br /&gt;
&lt;br /&gt;
Now
 I had a choice. I could stay, and drive development projects, leading a
 team of newly hired junior developers. My career would leap to a role 
of seniority and if I was to move on I could say I had been a &quot;senior&quot; 
developer.&lt;br /&gt;
&lt;br /&gt;
Or, I could move into a new company as a junior developer, where I would be mentored, and surrounded by more senior developers.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;I chose to move. &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I
 wanted to see how it was&quot;really&quot;done. How developers work together, how
 they feed off each other, how they learn. &lt;b&gt;I wanted to learn&lt;/b&gt;. I could 
not do that if I was the most senior developer.&lt;br /&gt;
&lt;br /&gt;
Staying was never
 an option. I&#39;d be a fraud. The title of senior can be extremely 
subjective, given for many reasons. Tenure, age, comparative skill, or 
genuine skill. &lt;br /&gt;
&lt;br /&gt;
Yet I see this often. Developers who have always 
been a senior developer don&#39;t get to see how it&#39;s &quot;really&quot; done, how skilled software departments work together. You can&#39;t always work out the best ways to do things by yourself. You need exposure to different practices, methodologies, cultures, personalities, and skill levels. &lt;br /&gt;
&lt;br /&gt;
Moving to a junior 
role was the best thing I ever did for my career. It taught me to 
understand the development process from the ground up, filling in many 
skills gaps from being self taught. Some of these skills were technical,
 some were interpersonal, but the most important, were both.&lt;br /&gt;
&lt;br /&gt;
Now I realise that the maintainability of our code is one of our most important skills as a developer. It&#39;s often said that we write code once and maintain it ten times. Most importantly, other people maintain it. &lt;span style=&quot;font-size: small;&quot;&gt;If your code isn&#39;t maintainable, then bugs happen.&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-size: large;&quot;&gt;If your code is not maintainable, &lt;i&gt;it can bring down companies&lt;/i&gt;.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;
Senior
 developers who have always been senior may not learn the importance of maintainability. They never have the pleasure of being told off by more senior developers for sloppy, non-reusable code. They didn&#39;t have the privilege of being humble and being shown how to write code that others can work with. Nobody complains to them about their code because they are always more senior. So they tend to get away with it, and often end up in charge of a hard-to-maintain monolith that nobody wants to work with.&lt;br /&gt;
&lt;br /&gt;
Senior developers should recognise that without exposure to different working dynamics, or other developers who have worked in different environments, they may be missing out.&lt;br /&gt;
&lt;br /&gt;
Management should compliment in-house, home-grown senior developers with senior developers who have experience where they were not the most senior. Well rounded senior developers with a broad range of experience, who are not afraid to speak up when code is not written with others in mind.&lt;br /&gt;
&lt;br /&gt;
If I had stayed as a &quot;senior&quot; developer, I may never have learnt the value of writing code for others.&amp;nbsp; And I may not even have realised it. &lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4751892421348729985'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4751892421348729985'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2018/04/being-senior-developer-means-more-than.html' title='Being a Senior Developer is more than being a long serving developer'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-3690231837213427340</id><published>2018-03-26T03:23:00.000+00:00</published><updated>2018-03-26T04:29:49.917+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Code Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="SRP"/><title type='text'>Ways to Spot Single Responsibility Violations</title><content type='html'>&lt;br /&gt;
Classes should only have one reason to change. We should attempt to increase cohesion between things that change for the same reason, and decrease the coupling between things that change for different reasons. Classes should do one thing and one thing well.&lt;br /&gt;
&lt;br /&gt;
Violations of the Single Responsibility Principle can cause code to be 
difficult to test and maintain, and can make it easier for bugs to 
manifest.&lt;br /&gt;
&lt;br /&gt;
There are a few symptoms of SRP violations which can give warning signs of these issues.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Large classes/methods&lt;/h3&gt;
&lt;br /&gt;
Obviously large classes and methods do not always point to SRP violations as there may be a requirement for a significant amount of logic. However, it is usually a good sign.&lt;br /&gt;
&lt;br /&gt;
Large methods are more likely to point to an SRP violation than large classes, or at least too much cyclomatic complexity. You&#39;ll become aware of this when you attempt to cover the method with test cases, and realise there are excessive test combinations required.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Too many injected dependencies&lt;/h3&gt;
&lt;br /&gt;
While this may depend a lot on how you set up your services, lots of injected dependencies may suggest that the class is doing too much, and may be violating SRP.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Too many tests per class&lt;/h3&gt;
&lt;br /&gt;
If a class has too many tests, or the tests need to change often, this is an indication that there may be too much complexity, too much setup, and this may point to an SRP violation.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Described with and/or, or encompassing words such as &quot;manager&quot;&lt;/h3&gt;
&lt;br /&gt;
This is a sure sign that your class or method is doing more than one thing. For example: a method called CreateOrEditRecord() or a class called &quot;InvoiceHandler&quot; are red flags, and should be investigated.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Logic in Views&lt;/h3&gt;
&lt;br /&gt;
Logic in your front end almost always means that you are violating SRP, because a view&#39;s responsibility is to render an output. As soon as you have two pieces of logic in a view, it&#39;s unlikely they&#39;ll be for the same reason, because they&#39;ll be for different elements on the page. This immediately makes it impossible to &lt;b&gt;unit&lt;/b&gt; test the view.&lt;br /&gt;
&lt;br /&gt;
Also, because of the standalone nature of views, there&#39;s a good chance you&#39;ll have to violate DRY in another view.&lt;br /&gt;
&lt;br /&gt;
Move that logic up to a model, a controller, a helper, or a service where it can be properly unit tested. </content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/3690231837213427340'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/3690231837213427340'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2018/03/ways-to-spot-single-responsibility.html' title='Ways to Spot Single Responsibility Violations'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-4678895821610311710</id><published>2015-12-17T10:57:00.000+00:00</published><updated>2018-03-26T02:22:16.499+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Certification"/><category scheme="http://www.blogger.com/atom/ns#" term="Learning"/><title type='text'>Microsoft Certified Solutions Developer!</title><content type='html'>After 3 years, 3 exams, and an excessive amount of study I have achieved the Microsoft Certified Solutions Developer - Web Applications certification.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://4.bp.blogspot.com/-EX8DYyhM8FA/VTTaeU0TrPI/AAAAAAAAFbs/NZf2ugsoYzsoQtHEwzZlkU-b0JvccBesQCPcBGAYYCw/s1600/MS_Cert_Professional_logo_Blk_rgb.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;733&quot; data-original-width=&quot;1117&quot; height=&quot;209&quot; src=&quot;https://4.bp.blogspot.com/-EX8DYyhM8FA/VTTaeU0TrPI/AAAAAAAAFbs/NZf2ugsoYzsoQtHEwzZlkU-b0JvccBesQCPcBGAYYCw/s320/MS_Cert_Professional_logo_Blk_rgb.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I realise that many people don&#39;t put a huge amount of emphasis on exams,
 valuing real world experience instead. But I have found that what
 I learned studying for these exams has been extremely valuable to my profession, helping me make more informed 
decisions in my day to day work.&lt;br /&gt;
&lt;br /&gt;
There is no substitute for real world 
experience, but real world experience leaves a lot of gaps and doesn&#39;t 
always teach the best habits. The exams have enabled me to fill in these gaps and develop a real 
technical proficiency which I may not have had without them.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
Born to Learn just posted this blog talking about a recent study which found 4 advantages certified staff have over non-certified staff, there are some interesting findings! &lt;a href=&quot;https://borntolearn.mslearn.net/b/weblog/archive/2016/01/25/four-solid-reasons-to-hire-certified-employees&quot;&gt;https://borntolearn.mslearn.net/b/weblog/archive/2016/01/25/four-solid-reasons-to-hire-certified-employees&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/4678895821610311710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2015/12/microsoft-certified-solutions-developer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4678895821610311710'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/4678895821610311710'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/12/microsoft-certified-solutions-developer.html' title='Microsoft Certified Solutions Developer!'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://4.bp.blogspot.com/-EX8DYyhM8FA/VTTaeU0TrPI/AAAAAAAAFbs/NZf2ugsoYzsoQtHEwzZlkU-b0JvccBesQCPcBGAYYCw/s72-c/MS_Cert_Professional_logo_Blk_rgb.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-9061703407675836276</id><published>2015-10-27T20:50:00.001+00:00</published><updated>2021-09-23T00:26:17.169+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Architecture"/><category scheme="http://www.blogger.com/atom/ns#" term="Cloud"/><title type='text'>Amazing Things You Can Do With Azure Storage Queues</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-NrJ_bENDRNU/YUvJl3iuTuI/AAAAAAABQQo/BbhteXlBhysmQijkG5O7XJxbYc6ZoLwOgCLcBGAsYHQ/s474/OIP.JauxOh_XTNmD_PQprZmG3wHaHa.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;474&quot; data-original-width=&quot;474&quot; height=&quot;640&quot; src=&quot;https://1.bp.blogspot.com/-NrJ_bENDRNU/YUvJl3iuTuI/AAAAAAABQQo/BbhteXlBhysmQijkG5O7XJxbYc6ZoLwOgCLcBGAsYHQ/w640-h640/OIP.JauxOh_XTNmD_PQprZmG3wHaHa.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h3&gt;Load Balancing and Workload distribution&lt;/h3&gt;
Queues can be used to organise the distribution of a workload across multiple processors.
&lt;br /&gt;
&lt;br /&gt;
A common technique is to post messages to a queue which are a key to a task which needs to be performed, and have multiple worker processes pick these tasks from the queue to perform in parallel. 
&lt;br /&gt;
&lt;br /&gt;
This can be combined with other storage mechanisms to perform complex tasks. Say you were trying to render an animation. The queue could be loaded with keys, which point to an entity in Table storage. This entity could contain the Url of an image stored in blob storage. A worker process would pick up the message from the queue, reference the entity from the table and download the image from blob storage. It could then perform compute intensive tasks on the image while other worker processes picked up other images. 
&lt;br /&gt;
&lt;br /&gt;
In this way, cloud storage can be used to augment worker roles and perform powerful parallel operations.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Asynchronous Processing and Temporal Decoupling&lt;/h3&gt;
It might sound like something you do with a sonic screwdriver, but temporal decoupling simply means that senders and receivers don&#39;t need to be sending and receiving messages at the same time. With messages stored on the queue, they can be processed when the receiver is ready to do so, and the sender is not held up. 
&lt;br /&gt;
&lt;br /&gt;
This can be useful for performing background tasks which are not critical to the main operation of a program, for example, a web application, rather than providing a slow response, can just queue up a thumbnail generation process and respond to the user quickly. A game, which requires the utmost UI responsiveness, might store replay data asynchronously using queues. </content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9061703407675836276'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9061703407675836276'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/10/amazing-things-you-can-do-with-azure.html' title='Amazing Things You Can Do With Azure Storage Queues'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-NrJ_bENDRNU/YUvJl3iuTuI/AAAAAAABQQo/BbhteXlBhysmQijkG5O7XJxbYc6ZoLwOgCLcBGAsYHQ/s72-w640-h640-c/OIP.JauxOh_XTNmD_PQprZmG3wHaHa.jpg" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-124624925679439503</id><published>2015-10-05T22:28:00.000+00:00</published><updated>2021-10-12T22:28:27.040+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET"/><category scheme="http://www.blogger.com/atom/ns#" term="async"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><title type='text'>Calling Long Running Methods Asynchronously</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-n551wLYAs2w/YWYLutpRw-I/AAAAAAABQpo/mfoLzN4KKdYLE0i7QQZC7FK92M3_lDn5wCLcBGAsYHQ/s744/async-header.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;195&quot; data-original-width=&quot;744&quot; height=&quot;168&quot; src=&quot;https://1.bp.blogspot.com/-n551wLYAs2w/YWYLutpRw-I/AAAAAAABQpo/mfoLzN4KKdYLE0i7QQZC7FK92M3_lDn5wCLcBGAsYHQ/w640-h168/async-header.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;When you are able to call an async method, do it using async and await or by making your method return a Task: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;ublic &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Task&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;RequestData&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;return
await&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient.DownloadStringTaskAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;// Rely on underlying Tasks
whenever possible.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;RequestDataAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient.DownloadStringTaskAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;// Rely on underlying Tasks
whenever possible.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Dealing with synchronous calls &lt;br /&gt;&lt;/h3&gt;&lt;p&gt;When the method you are calling is not asynchronous, wrap the method in a task delegate:&lt;br /&gt;
&lt;/p&gt;&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;&amp;nbsp;&lt;/span&gt;

&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;RequestDataAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;.Run&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;() =&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient.DownloadString&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;// Create Tasks when you have no
other choice.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;
&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Capturing Exceptions &lt;/h3&gt;&lt;p&gt;Getting a little more advanced, what if you might need to capture exceptions from a long running method? Use the following pattern:&lt;br /&gt;
&amp;nbsp;

&lt;br /&gt;
&lt;/p&gt;&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;RequestDataAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;tcs&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
= &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;span style=&quot;mso-tab-count: 1;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;TaskCompletionSource&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #2b91af; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #2B91AF; mso-style-textfill-type: solid;&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient.DownloadStringCompleted&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; +=&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(_, &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;) =&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;tcs.SetResult&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;args.Result&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;webClient.DownloadStringAsync&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;uri&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: blue; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: blue; mso-style-textfill-type: solid;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;tcs.Task&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: black; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: black; mso-style-textfill-type: solid;&quot;&gt;}
&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;// Example of wrapping &lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;Async&lt;/span&gt;&lt;span style=&quot;background: white none repeat scroll 0% 0%; color: #00b050; font-family: Consolas; font-size: 10.5pt; language: en-US; mso-ascii-font-family: Consolas; mso-bidi-theme-font: minor-bidi; mso-fareast-theme-font: minor-fareast; mso-font-kerning: 12.0pt; mso-highlight: white; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #00B050; mso-style-textfill-type: solid;&quot;&gt;/Completed.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;More info&lt;/h4&gt;&lt;p&gt;
Async&#39;ing Your Way to a Successful App with .NET &lt;br /&gt;
&lt;a href=&quot;http://channel9.msdn.com/Events/Build/2013/3-301&quot;&gt;http://&lt;/a&gt;&lt;a href=&quot;http://channel9.msdn.com/Events/Build/2013/3-301&quot;&gt;channel9.msdn.com/Events/Build/2013/3-301&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Creating Async Libraries That Are Modular, Reusable and Fast, in Microsoft Visual C# and Visual Basic &lt;br /&gt;
&lt;a href=&quot;http://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318&quot;&gt;http&lt;/a&gt;&lt;a href=&quot;http://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318&quot;&gt;://&lt;/a&gt;&lt;a href=&quot;http://channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318&quot;&gt;channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div style=&quot;direction: ltr; language: en-AU; line-height: 120%; margin-bottom: 0pt; margin-left: 0in; margin-top: 0pt; mso-line-break-override: none; punctuation-wrap: hanging; text-align: left; unicode-bidi: embed; word-break: normal;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/124624925679439503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2015/10/calling-long-running-methods.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/124624925679439503'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/124624925679439503'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/10/calling-long-running-methods.html' title='Calling Long Running Methods Asynchronously'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-n551wLYAs2w/YWYLutpRw-I/AAAAAAABQpo/mfoLzN4KKdYLE0i7QQZC7FK92M3_lDn5wCLcBGAsYHQ/s72-w640-h168-c/async-header.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-9068213455567767709</id><published>2015-08-20T01:26:00.001+00:00</published><updated>2021-09-23T00:28:21.958+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Developer Tips"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="NuGet"/><title type='text'>NuGet Like a Boss: Part 1 - Don&#39;t Check in Packages</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: right;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-T3XqBfM9OQk/YUvJ3amdRII/AAAAAAABQQw/DG6ORPsNK4glmEzEetYtEJ9Wcq3jwd8BACLcBGAsYHQ/s364/R.9516a836cae4abaea534e034b5c0bb08.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;363&quot; data-original-width=&quot;364&quot; height=&quot;319&quot; src=&quot;https://1.bp.blogspot.com/-T3XqBfM9OQk/YUvJ3amdRII/AAAAAAABQQw/DG6ORPsNK4glmEzEetYtEJ9Wcq3jwd8BACLcBGAsYHQ/w320-h319/R.9516a836cae4abaea534e034b5c0bb08.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;After suffering like many with so many Package Restore woes in my projects I decided to make notes on the best way to deal with Nuget packages. &lt;br /&gt;
&lt;/p&gt;&lt;h3&gt;
Ignore the packages folder&lt;/h3&gt;

Not doing this means you check in the packages which are huge. This is annoying and kind of defeats the purpose of Nuget. When you ignore (and therefore don&#39;t check in) your packages folder, anyone getting your source code can run package restore on the solution and Nuget will download the packages automatically. &lt;br /&gt;

&lt;h3&gt;
How?&lt;/h3&gt;

First, add a file named &lt;b&gt;.tfignore&lt;/b&gt;. This may require some Command prompt renaming as some set ups don&#39;t like files beginning with a dot. When you get past this annoyance, open the file in notepad and enter the following:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;\packages&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That tells TFS to ignore the packages folder. For some bizarre reason, this doesn&#39;t include the respositories.config file. You&#39;ll need to add a second line as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;!\packages\repositories.config&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You&#39;d think this would be it, but you may notice that your packages folder is already in your Pending changes. To get around this, create a folder called .nuget (command prompt trickery may be required) and in there create a file called NuGet.config. It must go in this folder, even if you have another NuGet.config at solution level. Enter the following text:&lt;br /&gt;
&lt;div style=&quot;font-family: Calibri; font-size: 11pt; margin: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;color: #222222; font-family: Consolas; font-size: 9.75pt; margin: 0in;&quot;&gt;
&lt;span style=&quot;background: rgb(238, 238, 238) none repeat scroll 0% 0%;&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;
encoding=&quot;utf-8&quot;?&amp;gt;&lt;br /&gt;
&amp;lt;configuration&amp;gt;&lt;br /&gt;
&amp;nbsp; &amp;lt;solution&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add
key=&quot;disableSourceControlIntegration&quot; value=&quot;true&quot;
/&amp;gt;&lt;br /&gt;
&amp;nbsp;
&amp;lt;/solution&amp;gt;&lt;br /&gt;
&amp;lt;/configuration&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
This should ensure that your packages stay out of source control. &lt;br /&gt;
&lt;br /&gt;
Finally ensure that .tfignore and NuGet.config are added to source control so that these settings should apply for anyone using the project. &lt;br /&gt;
&lt;h3&gt;
Gotcha!&lt;/h3&gt;

Be aware that the .tfignore file may not work if someone has already checked in the packages folder. Delete this from source control and you should be good.</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9068213455567767709'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/9068213455567767709'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/08/nuget-like-boss-part-1-dont-check-in.html' title='NuGet Like a Boss: Part 1 - Don&#39;t Check in Packages'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-T3XqBfM9OQk/YUvJ3amdRII/AAAAAAABQQw/DG6ORPsNK4glmEzEetYtEJ9Wcq3jwd8BACLcBGAsYHQ/s72-w320-h319-c/R.9516a836cae4abaea534e034b5c0bb08.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-5670371629510167383</id><published>2015-08-10T22:22:00.000+00:00</published><updated>2018-03-26T05:21:06.561+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cloud"/><title type='text'>Developing for the Cloud - An Introduction   </title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-Ap_nT-QRnxI/VckkQssyWXI/AAAAAAAALZI/K8lpAvTZnlQ/s1600/Cloud-500x250.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://3.bp.blogspot.com/-Ap_nT-QRnxI/VckkQssyWXI/AAAAAAAALZI/K8lpAvTZnlQ/s400/Cloud-500x250.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
When you create a web application for the cloud, there are many things that need to be done differently. It&#39;s not just a case of saying &quot;I&#39;m doing cloud&quot; and all you&#39;re really doing is putting it on someone else&#39;s VM. Doing this, the costs are much higher than if the application is designed with cloud in mind. This might be fine from an infrastructure point of view, but the cloud can have profound impacts on development from the ground up.&lt;br /&gt;
&lt;br /&gt;
Azure allows us, and also forces us, to engineer our applications completely differently. 
  &lt;br /&gt;
&lt;br /&gt;
Forces? Well, this is because when you&#39;re hosting in an App Service plan, you&#39;re billed based on compute time and resource usage. This forces you to write more efficient code. You can&#39;t just write code that performs unnecessary operations and get away with it - the efficiency of code now directly translates to dollars. This demands that you think twice when writing code, espcially loops, to ensure you&#39;re being efficient. Caching becomes a major priority so that you&#39;re not hitting a database unless you absolutely have to. 
  &lt;br /&gt;
&lt;br /&gt;
With the weight of costs, you need to start thinking about more efficient ways of doing everything. Luckily Azure offers many services to help increase application efficiency. The most basic example is storing images and other static resources in Blob storage. This is fast, lightweight, and extremely cheap. 
  &lt;br /&gt;
&lt;br /&gt;
Scripts and CSS can be offloaded to localised CDNs. This also increases speed and significantly decreases cost.
  &lt;br /&gt;
&lt;br /&gt;
Some data can shift from SQL to NoSQL models such as Table Storage, DocumentDB, or Graph data with its powerful relational features. An application might use all of these data types simultaneously for different purposes. For example, a shopping cart site might use SQL to store a user&#39;s identity information, Table storage to manage their shopping cart, DocumentDB to store product details, and Graph data to build &quot;You might also like&quot; links.
  &lt;br /&gt;
&lt;br /&gt;
Need to run asynchronous/background tasks such as generating thumbnail images? Use Web jobs to run scripts, executable, and third party libraries completely outside of the typical web application Request/Response lifetime. Use queues to decouple logic from the main workflow, or use multiple worker threads to perform parallel processing. 
  &lt;br /&gt;
&lt;br /&gt;
We can also take advantage of  Azure Search (powerful search services),  Service bus (host web services locally but expose them via the cloud), Azure machine learning (predictive analytics, data mining, and AI), and Notification hubs (push messages down to clients). 
  &lt;br /&gt;
&lt;br /&gt;
Then, we can host our applications in App Service plans (instead of Virtual Machines) and take advantage of Visual Studio Online&#39;s build and Continuous Integration features. We can also leverage elastic scaling and Application Insights.
  &lt;br /&gt;
&lt;br /&gt;
There are many more features in Azure and more appearing every day.
  &lt;br /&gt;
&lt;br /&gt;
To summarise, developing for the cloud is very different from building a website that will be isolated on a local server. It&#39;s a far more distributed model where separation of concerns is much more pronounced than we&#39;re used to. Developers and architects will need to think differently when designing applications. 
  &lt;br /&gt;
&lt;br /&gt;
This is just an intro to cloud features. In the future I will go into cloud architectural design patterns which allow us to design our applications to be resilient in failure-heavy environments. </content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5670371629510167383'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5670371629510167383'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/08/developing-for-cloud-introduction.html' title='Developing for the Cloud - An Introduction   '/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://3.bp.blogspot.com/-Ap_nT-QRnxI/VckkQssyWXI/AAAAAAAALZI/K8lpAvTZnlQ/s72-c/Cloud-500x250.jpg" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-8499467866687390940</id><published>2015-06-23T23:17:00.000+00:00</published><updated>2021-09-23T01:51:15.994+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Personal Development"/><title type='text'>How to Be an Organised Developer (and spend more time coding!)</title><content type='html'>As a developer your main focus is to write code. But over time, you&#39;ll find that there is a lot more to development than this. If you&#39;re not aware of this, you might one day wake up and realise that the notepad file you used for passwords and connection strings has gotten out of hand.&lt;br /&gt;
&lt;br /&gt;
Being more organised from the start can help keep you focussed on coding and help you stay more efficient. If you move jobs you&#39;ll pick up a lot of information in the first few weeks, you&#39;ll want to organise it well from the start. If you stay in the same job for years, the &#39;other stuff&#39; you accumulate can get messy and cumbersome.&lt;br /&gt;
&lt;br /&gt;
Like good code, making an effort to organise yourself well from the start can pay dividends later on, when it comes to navigating and maintaining all your stuff. 

Here&#39;s a list of some of the &quot;stuff&quot; you&#39;ll find yourself accumulating as a developer, and how to keep it well organised. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
OneNote (or Equivalent)&lt;/h3&gt;
An essential tool for all developers.&lt;br /&gt;
&lt;br /&gt;
The main thing this is useful for is storing essential information such as test data, database names, licence numbers for tools such as Resharper and Linqpad, and lists.&lt;br /&gt;
&lt;br /&gt;
You can also use it for debugging information, screen grabs, functional specs, checklists and pretty much anything you can think of. OneNote allows you to organise all this quite effectively with its use of tabs and pages.&lt;br /&gt;
&lt;br /&gt;
Note that by &quot;equivalent&quot;, I don&#39;t mean Notepad++. You need your notes in one well organised and secure location (save your notebooks remotely), you don&#39;t want to have to worry about hitting &quot;Save&quot;, and you also need to be able to paste in screen grabs, tables and other rich content. Evernote might come close but OneNote is trusted in enterprise environments which can give it the edge. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Logging Access&lt;/h3&gt;
Pretty soon you&#39;re going to need to access logs for auditing, testing or debugging purposes. Remember to record all details in your note software. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Product Documentation/Wikis&lt;/h3&gt;
As a developer you will probably be responsible for writing a lot of documentation. Make sure it&#39;s in an easily discoverable place and well maintained. Good code should be self-documenting, yes, but other stakeholders need to know what the code is doing from a non-technical perspective. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Bookmarks&lt;/h3&gt;
You&#39;ll always have a selection of really important links. This might include:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Product documentation/wikis&lt;/li&gt;
&lt;li&gt;Test Harnesses&lt;/li&gt;
&lt;li&gt;ALM tools (TFS, Git)&lt;/li&gt;
&lt;li&gt;Communication tools (Sharepoint, Trello)&lt;/li&gt;
&lt;li&gt;Administration tools (Timesheets, financial, personnel software)&lt;/li&gt;
&lt;li&gt;Development learning materials, tutorials, blog posts, communities etc.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
Figure out the best way to organise these based on your needs and make sure they&#39;re backed up and accessible everywhere (use Chrome/Firefox Sync or a bookmarks manager).&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
SQL Files&lt;/h3&gt;
Most developers will probably have a collection of SQL files of common, useful queries, for logging, basic CRUD, etc. Make sure these are in an easy to access, secure, backed up and preferably remote location. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Macros&lt;/h3&gt;
Specifically in Web Development, tools such as iMacros can be invaluable for automating frequent tasks such as logging in to test sites or running common actions on test harnesses. Remember, keep them well organised and backed up remotely using Dropbox/OneDrive etc. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Powershell Scripts and batch files&lt;/h3&gt;
You might also have some PC management tasks that need to be automated. Powershell is fantastic for these kind of tasks, and is becoming even more useful with the advent of DSC. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Linqpad Scripts&lt;/h3&gt;
Similarly, Linqpad allows for frequently used code to be stored and used in a lightweight manner without all the project overhead. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Code Toolbox&lt;/h3&gt;
Finally, all developers should have a code toolbox, or a collection of libraries and code snippets they use regularly in their projects. This is a lot to go into so I will create a new blog on it, but basically it could consist of 
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Project templates&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Emailing library&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Cloud storage library&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Logging classes&amp;nbsp;&lt;/li&gt;
&lt;li&gt;MVC Html helpers
etc&lt;/li&gt;
&lt;/ul&gt;
The idea is to allow for Rapid Development by having everything you frequently need at your fingertips and not having to worry about finding code for frequently performed tasks such as input forms or membership features. As I said, I&#39;ll give this topic a blog of its own soon. 

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
Hopefully this has inspired you to ditch that pile of text files and get your administrative stuff in order. Doing so will make you more efficient and help you focus on what&#39;s really important - writing code. 
&lt;br /&gt;
&lt;br /&gt;
How do you organise yourself? Is there anything I&#39;ve missed? Leave a comment!</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/8499467866687390940/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2015/06/how-to-be-organised-developer-and-spend.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/8499467866687390940'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/8499467866687390940'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/06/how-to-be-organised-developer-and-spend.html' title='How to Be an Organised Developer (and spend more time coding!)'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-5772392750273712730</id><published>2015-05-29T05:36:00.001+00:00</published><updated>2021-09-23T00:05:05.304+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Code Quality"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing"/><title type='text'>Why Bother With Unit Tests?</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-fiJM9zSTxAg/YUvEbzCTV0I/AAAAAAABQQA/SM767IrCdvcJhmPn_DvpBG5MevVAi_IlwCLcBGAsYHQ/s700/lego-light-purple-brick-2-x-2-3003-2-939628-69.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;700&quot; data-original-width=&quot;700&quot; height=&quot;400&quot; src=&quot;https://1.bp.blogspot.com/-fiJM9zSTxAg/YUvEbzCTV0I/AAAAAAABQQA/SM767IrCdvcJhmPn_DvpBG5MevVAi_IlwCLcBGAsYHQ/w400-h400/lego-light-purple-brick-2-x-2-3003-2-939628-69.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;I still see a lot of scepticism on WHY we should do Unit Tests and if they&#39;re really worth it. 
 &lt;br /&gt;
&lt;br /&gt;
Of course, they usually add time to the development cycle. They can be hard to create. Quite often, they seem pointless; Why do I need to check if my TwoTimesTwo() method returns 4? Of course it&#39;s going to! 
 &lt;br /&gt;
&lt;br /&gt;
Well, the benefits of Unit Tests may not always be obvious. Often they&#39;re disconnected from the problems caused by not doing them. For example, a manager is not likely to blame a Production issue on the fact that you didn&#39;t do Unit tests. 
&lt;br /&gt;
&lt;br /&gt;
Most of the time, if you release some code that performs what it needs to, nobody cares about the quality. However, the people who will care, are those who want to maintain your code later, especially if it ends up being:&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;You; or&amp;nbsp;&lt;/li&gt;
&lt;li&gt;A violent psychopath who knows where you live&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Unit Tests can also help to document code, showing you what it should and shouldn&#39;t be doing. They can help you understand it better.&lt;br /&gt;
&lt;br /&gt;
But maintainability still isn&#39;t enough for many people. 
 &lt;br /&gt;
&lt;br /&gt;
Personally I don’t think anyone can really understand the benefits of Unit Testing until they&#39;ve written some, and felt the satisfaction of  those green ticks, and the confidence they give you. Your code is now rock solid, nobody is going to break it without knowing about it (including yourself).&lt;br /&gt;
&lt;br /&gt;
With Unit Tested code you can be sure that every component is doing what it should be. Acceptance Criteria is another step and I&#39;m a strong proponent of automated behaviour driven integrated tests too. But Unit Tests can be more granular, covering a vast array of tiny details that can otherwise be easily overlooked and become the source of fiddly bugs later on. Also, when bugs are found, usually this results in messy, band aid fixes which make the code less flexible. TDD makes the code more maintainable to start with. The necessity to write SOLID code is increased by the need to ensure the code is highly modular and interface driven.&lt;br /&gt;
&lt;br /&gt;
In the end, the extra time spent building unit tests is returned several times by spending less time fixing 
bugs and maintaining messy code.&lt;br /&gt;
&lt;br /&gt;
The best way to see the benefits of Unit Tests is to write some. Start easy by writing one specifically to test a bug fix. You can then be sure that bug will never surface again. 
 &lt;br /&gt;
&lt;br /&gt;
Getting started is hard, don&#39;t get me wrong. It&#39;s like lifting weights for the first time, it&#39;s going to hurt. But push through the pain and you&#39;ll start to see the benefits. It will get easier. </content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5772392750273712730'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5772392750273712730'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/05/why-bother-with-unit-tests.html' title='Why Bother With Unit Tests?'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-fiJM9zSTxAg/YUvEbzCTV0I/AAAAAAABQQA/SM767IrCdvcJhmPn_DvpBG5MevVAi_IlwCLcBGAsYHQ/s72-w400-h400-c/lego-light-purple-brick-2-x-2-3003-2-939628-69.jpg" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-5936424439642373353</id><published>2015-04-01T09:07:00.000+00:00</published><updated>2022-07-10T12:10:16.835+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="business ideas"/><category scheme="http://www.blogger.com/atom/ns#" term="Creativity"/><category scheme="http://www.blogger.com/atom/ns#" term="ideas"/><category scheme="http://www.blogger.com/atom/ns#" term="Money &amp; Business"/><title type='text'>The Idea is the Easy Part</title><content type='html'>&lt;div style=&quot;text-align: center;&quot;&gt;&lt;figure aria-describedby=&quot;caption-attachment-6613&quot; class=&quot;wp-caption aligncenter&quot; id=&quot;attachment_6613&quot; style=&quot;width: 601px;&quot;&gt;&lt;a href=&quot;http://poweressence.com/wp-content/uploads/2015/04/3168683736_304641aa66_b.jpg&quot;&gt;&lt;img alt=&quot;Courtesy https://www.flickr.com/photos/nhuisman/&quot; class=&quot;wp-image-6613&quot; height=&quot;402&quot; loading=&quot;lazy&quot; src=&quot;http://poweressence.com/wp-content/uploads/2015/04/3168683736_304641aa66_b-1024x685.jpg&quot; width=&quot;601&quot; /&gt;&lt;/a&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Most people are of the belief that coming up with an idea is hard. “If only I could think of an idea, I’d be able to create a business”, they say.&lt;/p&gt;&lt;p&gt;They also try and think too big. They hold out for that “killer app” or world changing concept. The next Facebook.&lt;/p&gt;&lt;p&gt;But business ideas don’t have to be that ambitious. And they certainly don’t have to be that difficult to come up with. All you need is this simple formula.&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Idea = Niche + Need&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Find a niche, find a need. It really is that simple. But let’s dig into it some more.&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Find a Niche&lt;/h2&gt;&lt;p&gt;A niche is a small area of interest. A specific area of the market for people with a specific interest.&lt;/p&gt;&lt;p&gt;Finding a niche is a balance between finding a market small enough to be focused but large enough to be worthwhile.&lt;/p&gt;&lt;p&gt;Finding the right niche can be difficult in itself, but it can be made easier by following what interests you. This is actually incredibly important. Focusing on an area that you’re passionate about will both inspire you and keep you involved when things get difficult.&lt;/p&gt;&lt;p&gt;Getting to know a niche will allow you to develop mastery, and this alone can open up many business opportunities. However, your skills don’t necessarily have to correspond to your niche. In fact, bringing fresh skills into a niche can open up plenty of opportunities on its own. For example, you could be an app developer interested in gardening, or a designer who enjoys surfing.&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Find a Need&lt;/h2&gt;&lt;p&gt;Once you have a niche, spend some time in it. Ideally you’ll already be doing this and will have been for some time. It’s a hobby, better yet a passion. You might even be working towards becoming an expert in some aspect of your niche.&lt;/p&gt;&lt;p&gt;The better you know your niche, the better you’ll be at seeing needs within it. It won’t be difficult, in fact you’ll probably become aware of so many needs that your problem will be choosing one.&lt;/p&gt;&lt;p&gt;You’ll have to weigh up what kind of resources are required, what is going to be easy to rapid-prototype, what could be profitable, and what area you have sufficient knowledge in. This is probably the topic for another article but for now, you should have no shortage of “ideas”. Remember, the idea doesn’t need to change the world. It just needs to fulfill a need.&lt;/p&gt;&lt;p&gt;So again, coming up with an idea is not “the hard part”. If you focus on a niche that interests you, spending some time getting to know it, learning its ins and outs, and perhaps becoming an expert in it, you should be able to identify plenty of needs.&lt;/p&gt;&lt;p&gt;Then it’s up to you to choose one that you’re in a position to fulfill.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://blog.stuartdobson.net/feeds/5936424439642373353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://blog.stuartdobson.net/2015/04/the-idea-is-easy-part.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5936424439642373353'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/5936424439642373353'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/04/the-idea-is-easy-part.html' title='The Idea is the Easy Part'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9566863.post-1896656558406207173</id><published>2015-03-20T01:16:00.002+00:00</published><updated>2018-03-26T04:34:34.957+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Deployment"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Quality"/><title type='text'>How to Reduce Deployment Risk</title><content type='html'>&lt;h3&gt;
Functionality Switches&lt;/h3&gt;
&lt;br /&gt;
Feature flags controllable by configuration or an &quot;admin tool&quot;, are an excellent way to deploy new features. When going live, you can turn on a feature only for your Production test user, and run some smoke tests,  before turning the feature on for the wider world.
&lt;br /&gt;
&lt;br /&gt;
Any issues found later can then easily be mitigated by &quot;switching off&quot; the broken features for live users, while at the same time, leaving them on for the test users so that some fault investigation can be done on Production. 
&lt;br /&gt;
&lt;br /&gt;
Providing there are no breaking regression changes, this will help to avoid rollbacks.
 &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Good logging&lt;/h3&gt;
&lt;br /&gt;
Every significant action should be monitored and logged. Obviously this includes calls to external services, but you should also strive to implement logging based on items in the Acceptance criteria. Log results of actions so that you can see if they match expectations. This allows for granular diagnosis so you can see exactly what isn&#39;t working and where. 
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Reduced Functionality Instead of Errors&lt;/h3&gt;
&lt;br /&gt;
A good, defensive technique is to fall back to previous functionality when something fails, rather than giving the user an error. Obviously this depends on the scenario and this won&#39;t always be possible. 
&lt;br /&gt;
&lt;br /&gt;
However, combined with functionality switches, this can allow users to continue to use your application while you identify a fault using your production test users. This is also greatly dependent on your logging, of course, as your fault will not be manifesting in the interface. 
</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/1896656558406207173'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/9566863/posts/default/1896656558406207173'/><link rel='alternate' type='text/html' href='https://blog.stuartdobson.net/2015/03/how-to-reduce-deployment-risk.html' title='How to Reduce Deployment Risk'/><author><name>Stuart Dobson</name><uri>http://www.blogger.com/profile/05875712935672926252</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVb_5_0rdHGzkrmEueUFYFVTfTHYfTl1ASOhaM6zb8clTMM9YKbbUB7JebpTbNzbrbI6JXdr-G4Qpi0tfCyKNw8kZfd4Od8X2psR1izp2JsMvG4Zvvr1f3nn6zvQHY7E/s113/Stu.jpg'/></author></entry></feed>