tag:blogger.com,1999:blog-15756148952899753802024-03-19T08:48:11.357+00:00Code Blockagerobert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-1575614895289975380.post-85133619071252310672022-09-28T16:27:00.005+01:002022-09-28T18:14:05.836+01:00I joined a team that doesn’t do stand-ups (SEND HELP!)<p>You join a team that doesn’t do stand-ups, after your initial panic what do you do? Just book the daily in? You can’t do that! You’re a leader that values your teams opinions and works to understand them, after all it’s their team as much as it is yours.</p>
<p>How about listing what you’re missing and see what they can do to fix that? If they fail you can justify your sorely missed daily!</p>
<p>Requirements List:</p>
<ul>
<li>You need to understand the state of the team, how tickets are progressing and how far along they are</li>
<li>Knowing about blockers are a must, you need to unblock them!</li><li>Understanding the plan for progressing the ticket is important too!</li>
</ul>
<p>You try a daily slack reminder where people can write the old yesterday, today and blockers in, but you’ve been <a href="https://www.youtube.com/watch?v=H02BlTXpcto">walking the board</a> for years now and this feels like a step backwards!</p>
<p>Focus on the board seems to be important, so you propose:</p>
<ul>
<li>They keep tickets updated with comments on progress as they move forward</li>
<li>When picking up a ticket for the first time a plan is added for the day</li>
<li>At the start of each day add a plan for the day to the tickets you’re working on</li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaMa3-UAfPVxXT2EbRO6MWT1QT1G3nC7nlDdjo68G894JlUUa8QyntutJBv88qsbxHtn-FZFLm-CEc5dhMn8f0W98RYQLcOrneX4Mo_xWPT5oIf0eNOhZ3YMWhsHjzVxkE_8NScHrsa-l4qDV1-AQFN0mne_y7-gdqK43LAYEkQFNqwLE4Yo4s7x8B/s6240/miikka-luotio-i3WlrO7oAHA-unsplash.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4160" data-original-width="6240" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaMa3-UAfPVxXT2EbRO6MWT1QT1G3nC7nlDdjo68G894JlUUa8QyntutJBv88qsbxHtn-FZFLm-CEc5dhMn8f0W98RYQLcOrneX4Mo_xWPT5oIf0eNOhZ3YMWhsHjzVxkE_8NScHrsa-l4qDV1-AQFN0mne_y7-gdqK43LAYEkQFNqwLE4Yo4s7x8B/w481-h320/miikka-luotio-i3WlrO7oAHA-unsplash.jpg" width="481" /></a></div>
<p>This becomes very hit and miss until, you <strong>unlock the power of the WIP limit!</strong> By reducing the amount of work the team is processing at once updating the board becomes much less effort, also you can quickly digest the current state of the team!</p>
<p><i>This was me six months ago, now I can happily say I don’t miss the daily stand-up any more and asynchronous communication is a super power we should all be unlocking.</i></p>
robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-32258659257574906692022-09-27T16:20:00.001+01:002022-09-27T16:42:21.454+01:00Reducing meeting pain<div>Our refinement sessions ran over every time without fail, we often repeated the same points and people weren’t always very engaged.</div><p>To fix this we set expectation that all tickets for the next session should be read and questions asked before the meeting. This wasn’t easy to get used to, but quickly the sessions shortened in length and everyone found that the meetings were much more valuable.</p>
<aside>
💡 If a meeting doesn’t have a <strong>pre-read & agenda</strong> then people come with different levels of understanding about the topic, and much time is spent making sure everyone understands what is being discussed. By the time you get to this point you may have lost the attention of the people who already understood.
</aside>
<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjGkSwxuPFQlQL-GvlmQjEMYQYDVkxZSCVicJnp--jY88i9dwKOGG7OhL5DoLqHk3UG38tt9qVu9iLUBpA1MTwAcs0HkOSyxEF_AHkcjYRXT_k01u7emFWm2mWlSgB8olDu3j-qHHIIOemwDdIlgqk4Si0QmxFUcCHg7-TVnTwWF5ciU7gXbBLWtX99" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="585" data-original-width="780" height="376" src="https://blogger.googleusercontent.com/img/a/AVvXsEjGkSwxuPFQlQL-GvlmQjEMYQYDVkxZSCVicJnp--jY88i9dwKOGG7OhL5DoLqHk3UG38tt9qVu9iLUBpA1MTwAcs0HkOSyxEF_AHkcjYRXT_k01u7emFWm2mWlSgB8olDu3j-qHHIIOemwDdIlgqk4Si0QmxFUcCHg7-TVnTwWF5ciU7gXbBLWtX99=w501-h376" width="501" /></a></div><br /><br /><p></p>
<p>I've tried to identify different types of meetings and suggest ideas to improve them.</p>
<h3 id="discussions">Discussions</h3>
<p>A discussion is an ad hoc focused meeting on a specific topic.</p>
<ul>
<li>Make sure there is a pre-read and an agenda!</li>
<li>Choose just the right amount of people to get the problem solved, don’t spam invite, talk to people before hand and see if their attendance makes sense</li>
<li>Encourage people to comment and ask questions on the pre-read</li>
</ul>
<h3 id="regular-meeting">Regular meeting</h3>
<p>Normally these meetings have a regular cadence, and discuss topics that affect a group of people in a similar role or domain.</p>
<ul>
<li>Have an agenda with the different topics</li>
<li>Make the meeting optional, so people can join to discuss the topics if they are interested</li>
<li>Record the meeting per topic, this is high effort but great for sharing after</li>
<li>Try to use a task board rather than a document for running meetings</li>
<li>Focus on discussions, announcements can go in slack or document based communication</li>
</ul>
<h3 id="status-meetings">Status meetings</h3>
<p>In these meetings often groups of people give updates on current progress, such as standups or project meetings. With stand-ups there has been a move from yesterday, today, blockers to <a href="https://www.youtube.com/watch?v=H02BlTXpcto">walking the board</a>, but the next step remotely seems to me to be everything should just be updated regularly.</p>
<ul>
<li>There should be somewhere, preferably automated where I can see the current state of a project/team quickly</li>
<li>These meetings are often low value for the majority of people, high value for a few and get worse the bigger the group</li>
<li>Try to automate status updates and have meetings for specific discussions</li>
</ul>
<h3 id="information-streaming">Information Streaming</h3>
<p>Normally a big group of people with a small group of talkers</p>
<ul>
<li>Could we just record videos or write articles to replace these?</li>
<li>Individual videos & articles are preferred as people can skip/skim the ones that aren’t relevant rather than forcing peoples attention</li>
</ul>
<h3 id="1-1s">1:1s</h3>
<ul>
<li>High value!</li>
<li>Have an agenda!</li>
</ul>
<h3 id="social-meetings">Social Meetings</h3>
<ul>
<li>Most important meetings in the calendar!</li>
<li>Try not to mix with work, these meetings are pure social so we can keep work meetings short and people can have breaks in between meetings</li>
<li>only meetings that should run to fill time, all other meetings we should be trying to reduce the amount of time, except maybe 1:1s?</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>The point here is not to have no meetings, but to make sure our meetings have the right amount of people for a reasonable amount of time. Freeing up more time can help give us more bandwidth for high value activities that come from the same bucket. 1:1s, pairing, etc. We can only really unlock the value from those if we don't ask people to use their energy on the others.</p>
<h3 id="call-to-action">Call to action</h3>
<p>Try out some tips, share your own! and we can all look forward to higher quality meetings!</p>
robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-26623330839787206672022-09-26T19:25:00.003+01:002022-09-26T19:25:46.623+01:00Why I rush into things (with rockets!)<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhDB1z5aafT_mAY9Cta3d-kixNEZ194yEK0flwFz1fsdt7w8HiVVY-gIPo6891hqTQjhXa4lFl8CMvy3fW8LDrYqrjdrkrPZHqATDtdoPnuvEVWkspS5427jtvyM6D-NzPT1UggTnAyJwRo6AeAWE5YnsEPxMj7oErSykq4Tko0ZcMY8wnEBACh8yl4" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="300" data-original-width="400" height="323" src="https://blogger.googleusercontent.com/img/a/AVvXsEhDB1z5aafT_mAY9Cta3d-kixNEZ194yEK0flwFz1fsdt7w8HiVVY-gIPo6891hqTQjhXa4lFl8CMvy3fW8LDrYqrjdrkrPZHqATDtdoPnuvEVWkspS5427jtvyM6D-NzPT1UggTnAyJwRo6AeAWE5YnsEPxMj7oErSykq4Tko0ZcMY8wnEBACh8yl4=w478-h323" width="478" /></a></div><br /><br /><p></p>
<p>This is starhopper, starhopper flew 150 meters into the air on the 25th July 2019, SpaceX had wanted to fly it higher but the FAA limited the flight to 150 meters. When it landed it smashed into the concrete landing pad, if it had gone higher it probably would have blown up.</p>
<p>Starhopper was <strong>just about good enough</strong> to fly, it had a high chance of failure and SpaceX learned a lot from flying this early prototype.</p>
<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEibajpVl-xszc6oWrU4Ens3zU3Dqdd8oU92LvWVMr0NLmUrC_L5jfy69oQKWNqgp1Z7_py6x0eH8D6G7iqxNBuk2G4U3gSoE82_tZFAhd2vlD3hlcnCxeZdq841nF9_oLncO2eDe_zB_D9YeCTCyd4aw8r1BANhTxK1PFImKdwfDPMQW1imLSkDfuuM" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1930" data-original-width="1458" height="441" src="https://blogger.googleusercontent.com/img/a/AVvXsEibajpVl-xszc6oWrU4Ens3zU3Dqdd8oU92LvWVMr0NLmUrC_L5jfy69oQKWNqgp1Z7_py6x0eH8D6G7iqxNBuk2G4U3gSoE82_tZFAhd2vlD3hlcnCxeZdq841nF9_oLncO2eDe_zB_D9YeCTCyd4aw8r1BANhTxK1PFImKdwfDPMQW1imLSkDfuuM=w332-h441" width="332" /></a></div><br /><br /><p></p>
<p>This is SN24 and booster 7, which may be the first prototypes to reach orbit (hopefully in the next couple of months) as you can see a lot has changed!</p>
<p>In between these there have been many prototypes and many tests.</p>
<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiFuEJsDdKsGX_yVJntzlvvMsx2PAmGP758pcvoma2jvXYrzED9ksfAo8MUMkGSFFSRP8xTRFZM3fbFWiXgLALaOHbS8LdsDlF2Q-UQdFWuVzHyDwL4l8FBTQJXUS4QBS48tbhTTyOtPXWzs_F1KuGpQveUl7b3Xp4Cg-X_Y_joHa1M4i8l5n-0b911" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="200" data-original-width="358" height="293" src="https://blogger.googleusercontent.com/img/a/AVvXsEiFuEJsDdKsGX_yVJntzlvvMsx2PAmGP758pcvoma2jvXYrzED9ksfAo8MUMkGSFFSRP8xTRFZM3fbFWiXgLALaOHbS8LdsDlF2Q-UQdFWuVzHyDwL4l8FBTQJXUS4QBS48tbhTTyOtPXWzs_F1KuGpQveUl7b3Xp4Cg-X_Y_joHa1M4i8l5n-0b911=w524-h293" width="524" /></a></div><br /><p></p>
<p><em>Apparently a green flame indicates engine rich exhaust, or your engine is burning up!</em></p>
<p>Through lots of iteration and testing often they have improved their next generation rocket a lot!</p>
<p>We generally build our software like this, but can we do everything like this? Don’t design things to be perfect, design them to learn and test them as soon as you can! Real world feedback is the only way to know for sure, and by showing people something early they suggest things that you wouldn’t have thought of!</p>
<p>Recently I've started running experiments to change meetings to be asynchronous, there's always the thought that it could have been organised better, or we should have tried something different. But the most important thing was we tried something, it was just about good enough, then we collected feedback. The feedback will get us to a great solution a lot faster than trying to answer questions ahead of time.</p>
robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-36539863230829023152022-09-09T17:46:00.003+01:002022-09-09T17:46:41.040+01:00What is async working and why should you be learning from it<p>Long before covid hit there were fully remote companies, some forced to be that way through being spread around the globe. They had to solve problems like how a team works together if they never had a time of the day when they can all interact through a meeting. These companies use what's known as asynchronous ways of working the main challenge being you probably won't get a reply from anyone quickly.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh6d6CfN_33PzHqkCn2P2K-Xn2cNOKlUDUGYWOUh0tbjm5-KskyDalkBtx4cjhPIV-qYSngyh7nj6SF7s16Atp1SxbI5CnM68F9OaviOpmXcFpFqdpvnc2KQDkeynORzfW3YTcD64TQXlXzQC5d5nz1_qz8cBJlvHKgDdYiFPSeIx_c5E20wsmUV45s" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="800" data-original-width="1000" height="374" src="https://blogger.googleusercontent.com/img/a/AVvXsEh6d6CfN_33PzHqkCn2P2K-Xn2cNOKlUDUGYWOUh0tbjm5-KskyDalkBtx4cjhPIV-qYSngyh7nj6SF7s16Atp1SxbI5CnM68F9OaviOpmXcFpFqdpvnc2KQDkeynORzfW3YTcD64TQXlXzQC5d5nz1_qz8cBJlvHKgDdYiFPSeIx_c5E20wsmUV45s=w468-h374" width="468" /></a></div><br /><br /><p></p><p>The practices focus around documentation first communication and empowering employees to do their job without the need for quick responses.</p><p>If you were working for a non-remote company when covid hit the cost of arranging a meeting was hugely reduced, we used to have limits like the number of rooms or the number of seats in a room. Now we could book a meeting to solve every problem and we did. In lots of companies, this is having a big impact, huge reductions in focus time! Also, the expectation of quick slack responses means constant interruptions further reducing focus time.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiaGXpCd1bRJhzMqBhYZ0kzSeuKD_TnkUu7Eq0_GBcJOvyjgHWPDE6Y6EEpEncPDI-c7IyIYgVeK38teMUk1iTX02X6vOs6MAS5hWrslz3yRThxVSLeGnGq3efzfnQhRO3Oi8KrJquaL6jlEmbVEuIIxEhpOSKKLROJvtCKU79tPLhF-8XW-DzNg8R1" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="756" data-original-width="500" height="474" src="https://blogger.googleusercontent.com/img/a/AVvXsEiaGXpCd1bRJhzMqBhYZ0kzSeuKD_TnkUu7Eq0_GBcJOvyjgHWPDE6Y6EEpEncPDI-c7IyIYgVeK38teMUk1iTX02X6vOs6MAS5hWrslz3yRThxVSLeGnGq3efzfnQhRO3Oi8KrJquaL6jlEmbVEuIIxEhpOSKKLROJvtCKU79tPLhF-8XW-DzNg8R1=w314-h474" width="314" /></a></div><br /><br /><p></p><p>By looking at async ways of working we can really start to take advantage of being remote, reduce meeting fatigue and increase productivity. Some of the advantages are:</p><p></p><ul style="text-align: left;"><li>Empower employees and give them ownership</li><li>Reduce the pain of employees in different timezones</li><li>Increase focus time, often leading to higher productivity</li><li>Stress-reducing, zoom fatigue is real</li><li>Gives people time to think and research before answering</li><li>Increases the quality of documentation (this has many benefits)</li></ul><p></p><p>A great example of how to supercharge your workflow with async practices is to expect everyone to comment and ask questions on tickets before your refinement sessions. If you're like me you'll find that refinement zoom calls often overrun and aren't very engaging. By setting the expectation that everyone has read the ticket, understood the problem, and suggested approaches before the meeting these meetings will be supercharged!</p>robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-64328656291133700512022-08-30T16:19:00.000+01:002022-08-30T16:19:38.779+01:00Trying out a WIP limit<p>Work-in-progress limits are used to reduce the number of things that are actively being worked on by your team at once. The columns on our board that represent in progress are developing, reviewing, and deploying.</p><p>We could assign limits to the number of cards in each column, all in progress columns or per user. For our experiment, we chose to assign the WIP limit across all 3 columns. So for the first two days, we could only have 2 items across all columns. </p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjHkuira5pOfF2vZ2IJWrrdivOcEFOLmKXTNsCeaPXKh9OZ98HYeKtkJCNE7b8AVZyGmnyN0IlFykDB_Q-I432Fbbf0GJDsmNOs04VPjpnQL-GddgO_vUL4ezoy1UHjcPqwqxVgskIbIjF_km2etPPOkN9d2_NsSGHDHi9xQG45D4zi6lvpXv_YrBes" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1080" data-original-width="1700" height="298" src="https://blogger.googleusercontent.com/img/a/AVvXsEjHkuira5pOfF2vZ2IJWrrdivOcEFOLmKXTNsCeaPXKh9OZ98HYeKtkJCNE7b8AVZyGmnyN0IlFykDB_Q-I432Fbbf0GJDsmNOs04VPjpnQL-GddgO_vUL4ezoy1UHjcPqwqxVgskIbIjF_km2etPPOkN9d2_NsSGHDHi9xQG45D4zi6lvpXv_YrBes=w470-h298" width="470" /></a></div><br /><br /><p></p><p>After activating this rule lots of things changed very quickly... </p><h2 style="text-align: left;">Quality improvements</h2><p>parts of our process that were not writing code increased in quality, we found that reviews had more people in them and were getting processed faster and with what felt like more detail in them. </p><p>Our process includes people reading and commenting on tickets before our elaboration sessions, in order to have a base understanding and shorter meetings. Sometimes it can be difficult to make sure this is being followed, this quickly improved and there were many insightful questions on the upcoming tickets as well as extra tickets not scheduled for elaboration. </p><h2 style="text-align: left;">Easier to understand what was happening </h2><p>As lead engineer i found it much easier to know what was going on, on the team. We dont have stand up meetings but follow some simple rules for ticket updates: comment an update on the ticket when picking it up, showing your plan for the day. </p><p></p><ul style="text-align: left;"><li>Comment an update each morning on tickets you own showing the plan to move it forward that day.</li><li>Comment general updates on tickets so people know what is going on.</li><li>Prefer talking on tickets over talking on slack, if you do talk on slack link in the ticket. </li></ul><p></p><p>This mixed with having less things on the board meant it was really easy to know the current state of the team with a glance at our board. It also made it a lot clearer what the bottlenecks in our process were, before we would not notice that a deployment of stored procedures took a long time, but after the change it became very painful and we had to address the problem. </p><h2 style="text-align: left;">Increased collaboration</h2><p>By having a limit that was less than the number of engineers on the team often people found themselves pairing on work more frequently in order to push tickets across the board. Collaboration is one of our teams values and our preferred way of working, the lower wip limits have really increased the amount of pairing going on!</p><h2 style="text-align: left;">Interesting points </h2><p>we had to be careful to split tickets so that we avoid enforced waits, as a blocked ticket would count against our wip limit. For example we might have to wait for a 3rd party to respond before we can continue working on a ticket. To get around this we would split the ticket around the wait so we have two tickets, one to send out information and one to process received updates. Sometimes even with a wip limit of 2 we still only had 1 ticket in play, im not 100% on what caused this but one thought is that once an engineer picks up an idle task such as doing some learning if a space then became available they wouldnt notice for a while. </p><h2 style="text-align: left;">Conclusion </h2><p>looking at our cycle time and ticket velocity from just after the experiment started, it appears that our cycle time was reduced, we saw an initial spike in velocity as we completed all the tickets in progress and then returned to a similar velocity as we had before. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXl3vYU3KVAEDeqsqnVeA-VAgt2MprvBAB2szUx4NJkJONLgQAXjbNoxLBZZkCZAVAzgAtSjkzXFLe5nRTu2vM712icFHC3pxZouej48yd5JHsXujqxGbPHe_zgVzXs_iL6wqSnHMmHeEkha71Un72vZzEPqqqic8dTKs3_SIqfCf4NNOJZ8_QciMe/s966/Screenshot%202022-08-22%20at%2016.56.12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="666" data-original-width="966" height="221" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXl3vYU3KVAEDeqsqnVeA-VAgt2MprvBAB2szUx4NJkJONLgQAXjbNoxLBZZkCZAVAzgAtSjkzXFLe5nRTu2vM712icFHC3pxZouej48yd5JHsXujqxGbPHe_zgVzXs_iL6wqSnHMmHeEkha71Un72vZzEPqqqic8dTKs3_SIqfCf4NNOJZ8_QciMe/s320/Screenshot%202022-08-22%20at%2016.56.12.png" width="320" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLcdn-NbyqN1peN63f_5b6oszXKJ6s0GJSZ3_-2Z3GfN5JeKAWx8Bs0kFi-UY9w-6kHq8Kshp7b7XAA34-39Vcgqf1IQbeWQztootezYayslcXTKiWYB9wFhOdcgOyghuesCvsujZKzyU3VcYTBRVKsI_TqWe-z4IWeiB3_hMwEIkXwoeUkDchLu56/s740/Screenshot%202022-08-23%20at%2014.43.47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="584" data-original-width="740" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLcdn-NbyqN1peN63f_5b6oszXKJ6s0GJSZ3_-2Z3GfN5JeKAWx8Bs0kFi-UY9w-6kHq8Kshp7b7XAA34-39Vcgqf1IQbeWQztootezYayslcXTKiWYB9wFhOdcgOyghuesCvsujZKzyU3VcYTBRVKsI_TqWe-z4IWeiB3_hMwEIkXwoeUkDchLu56/s320/Screenshot%202022-08-23%20at%2014.43.47.png" width="320" /></a></div><br /><p><br /></p><p>This is quite interesting as based on initial data it seems that we didnt hugely increase the amount we deliver in a given period but we did reduce cycle time which would allow us to change direction faster if we need to process some incoming work quickly. As well as what appears to be a big increase in team focus and quality. So weve decided to adopt a wip limit into our team ways of working, the value we decided on for now is (engineers / 2) + 1.</p>robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-32739792644470535412021-02-24T08:09:00.001+00:002021-02-24T08:09:27.862+00:00Leadership Learning<p><span style="font-family: helvetica;">Here is a list in no particular order of some sources of knowledge I have found inspiring lately, definitely worth a read if you manage people.</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">Elastic Leadership </span><a href="https://www.amazon.co.uk/Elastic-Leadership-Roy-Osherove/dp/1617293083/ref=sr_1_1?dchild=1&keywords=elastic+leadership&qid=1614152913&sr=8-1" style="font-family: helvetica;">amazon</a></h2><p><span style="font-family: helvetica;">This book really helped me to fill in my thinking around why when you aim to make teams autonomous sometimes you end up falling back to a more command and control style structure, and how to get back to autonomous self-learning teams.</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">Drive <a href="https://www.amazon.co.uk/Drive-Surprising-Truth-About-Motivates/dp/1786891700/ref=sr_1_1?dchild=1&keywords=drive+dan+pink&qid=1614152837&sr=8-1">amazon</a></span></h2><p><span style="font-family: helvetica;">A must-read if you're interested in what motivates people, which is often contrary to the way we operate by default.</span></p><h2><span style="font-family: helvetica;">Start with why <a href="https://www.amazon.co.uk/Start-Why-Leaders-Inspire-Everyone/dp/0241958229/ref=sr_1_1?crid=3H6XBG4LA8GON&dchild=1&keywords=start+with+why&qid=1614093849&sprefix=start+with+%2Caps%2C167&sr=8-1">amazon</a></span></h2><p><span style="font-family: helvetica;">A great look at leadership and how to inspire people. </span></p><h2><span style="font-family: helvetica;">Leaders eat last <a href="https://www.amazon.co.uk/Leaders-Eat-Last-Together-Others/dp/0670923176/ref=sr_1_1?dchild=1&keywords=leaders+eat+last&qid=1614153982&sr=8-1">amazon</a></span></h2><p><span style="font-family: helvetica;">A follow up to start with why, I love reading these books as they really draw a great picture of what a leader should be and how they should act.</span></p><h2><span style="font-family: helvetica;">Back to human <a href="https://www.amazon.co.uk/Back-Human-Leaders-Connection-Isolation/dp/0349422354/ref=sr_1_2?dchild=1&keywords=back+to+human&qid=1614153283&sr=8-2">amazon</a></span></h2><p><span style="font-family: helvetica;">Back to human is a great look at how to build a connected and engaged workforce, how to be an effective leader, and more.</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">No Rules Rules <a href="https://www.amazon.co.uk/No-Rules-Netflix-Culture-Reinvention/dp/0753553635/ref=sr_1_1?dchild=1&keywords=no+rules+rules&qid=1614152568&sr=8-1">amazon</a></span></h2><p><span style="font-family: helvetica;">A great look into the thinking behind how Netflix inspires innovation through autonomy and trust, I really liked their thinking around increasing performance through talent density, basically having the most performance from the least amount of people, I can see how this will reduce work through reduced communication channels.</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">Spotify engineering culture <a href="https://www.youtube.com/watch?v=4GK1NDTWbkY&t=6s">youtube</a></span></h2><p><span style="font-family: helvetica;">A great couple of videos about how Spotify encourages innovation and learning, so many great concepts, and a fun look inside a really interesting company.</span></p><h2 style="text-align: left;"><span style="font-family: helvetica;">Asynchronous development for hybrid remote dev teams <a href="https://linearb.io/our-mission/">website</a></span></h2><div><span style="font-family: helvetica;">A really interesting look at how remote engineering teams can work, although not really leadership related understanding how to set up a great remote working environment is only likely to become more important in a post-pandemic world where most engineers and companies have now seen how productive remote working can be, and that was when done in a panic, how much could we get out of remote working when we really take the time to optimize it.</span></div><div><span style="font-family: helvetica; font-size: small; font-weight: normal;"><br /></span></div><p><span style="font-family: helvetica;"><br /></span></p>robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-40760254275917480152018-08-30T09:03:00.001+01:002020-01-11T14:23:34.454+00:00TDD: design laterTDD is freaking awesome!<br />
<br />
<img alt="awesome GIF by Cartoon Hangover" height="359" src="https://media1.giphy.com/media/14dqBdYpVvdNvi/giphy.gif" width="640" /><br />
<br />
Seriously though, for most projects, TDD is a great place to start!<br />
<br />
Let's go on a TDD journey and see how it affects the design of a project!<br />
<br />
<img alt="leaving lets go GIF by Jim Gaffigan" height="479" src="https://media2.giphy.com/media/67Ti0sQqkMVELQUSED/200.webp" width="640" /><br />
<br />
So I'm working on a project, I have a reasonable idea of how I'm going to design the project and break up the abstractions. First I choose a central set of entities and begin writing tests for them.<br />
<br />
Through doing TDD I guarantee that the project is easily testable, because I have to write tests if I choose the wrong part to test or way to test it my life is going to be painful, so I would quickly reevaluate making the wrong decisions because I'm not having TDD fun I'm having TDD pain. TDD will quickly tell you if you're doing it wrong by being extremely painful to write the tests.<br />
<br />
As we go forward I follow my design and TDD enforces the testability of the design, and allows me to quickly refactor the design if I have miscalculated anything! Woohoo!<br />
<br />
<img alt="fun celebrate GIF by Shaun the Sheep" height="360" src="https://media0.giphy.com/media/xT0GqBJf5FNUGKoVrO/giphy.gif" width="640" /><br />
<br />
Another time, I'm building a new project, I have no clue about how to design it. I'm not really sure how it will interact with other systems. What the API should be and really where the abstractions lie internally.<br />
<br />
This time I just choose what seems a reasonable place to wrap the logic and begin writing tests, I write the hackiest ugliest code in a single file to satisfy the tests and focus on the quality of the tests, not the actual code. After working on the project for some time it's really going to start creaking, there are tonnes of conditional nested logic and edge cases are starting to become quite painful. But at some point, it becomes quite easy to sit down and come up with a design that actually satisfies the project.<br />
<br />
With design in hand, I can sit down bin off the file that I was using for the main code and leverage the tests to confirm that the new design works! GLORY!<br />
<br />
<br />
Don't agree? Leave a comment!<br />
<br />robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com1tag:blogger.com,1999:blog-1575614895289975380.post-6579965626472923912018-08-19T17:06:00.001+01:002018-08-19T17:06:24.892+01:00using errorsMuch error handling has to be tailored to the situation that suits it, at a minimum, you will want an overall error handler for an API call to handle unexpected errors and report them to the consumer and probably a log.<br />
<br />
<script src="https://gist.github.com/envman/b59c5cc53971914a233e769855330004.js"></script>
<br />
sometimes we can do something when an error occurs before it hits the default handler, in this case, we return cached data instead.<br />
<br />
<script src="https://gist.github.com/envman/5c46369e338ecc0f5d41c7bcb2db4b2d.js"></script>
<br />
One important thing to note is the extra value that is added when using the Error class even when rejecting a promise.<br />
<br />
<script src="https://gist.github.com/envman/ec83cabdf8c78757e57e1dde08296fb6.js"></script>
<br />
This will mean that when we log out the error in the error handler we also get a stack trace, as when a new error is created it records the current stack.<br />
<br />
In some cases, we may not be able to fix the problem but we may be able to add additional information to help us when reading the logs later.<br />
<br />
<script src="https://gist.github.com/envman/fd1aa919034c705906fb77ccdbd6e708.js"></script>
<br />
now the log will contain the user id and save us some time when debugging later!<br />
<br />
Some error cases may be something that we cannot do anything about but the user can, in this case, we are going to need to tell them about it, this hopefully saves us being contacted by the consumer/user and they can fix their own problem.<br />
<br />
<script src="https://gist.github.com/envman/9a0b32fbb9c264ceaaff0d4cc5a63b03.js"></script>
<br />
In this case, we create an additional error type that extends error so that we can bubble that up to be able to alert the user that their account is disabled.<br />
<div>
<br /></div>
robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-12350163707381654532018-08-18T11:44:00.002+01:002018-08-18T11:46:13.241+01:00express error handlingHere are a few ideas for error handling in an express app.<br />
<br />
For all cases, you will want every route to handle any errors that can occur so that we can notify the caller and potentially do some logging.<br />
<br />
<script src="https://gist.github.com/envman/d60c8f0a4f499005f88d88ff7c10d11d.js"></script>
Now, this can become quite tedious and repeated so we can pass the error to expresses default error handler!<br />
<br />
<script src="https://gist.github.com/envman/b5a8e927490ba1b72006ac0d9d8b66a1.js"></script>
This will cause express to pass the error out to the client, which in most cases is probably not what we want, so let's have a look at replacing the default error handling middleware.<br />
<br />
<script src="https://gist.github.com/envman/79ea741b6e1f8ca302d8d00b6503305c.js"></script>
This now gives us control to be able to add some default logging and return the status we want as well as and information we want to show to the consumer.<br />
<br />
One really important thing to remember is to put the function after you define your route handlers! Or it won't catch the errors. (at the bottom of the file)<br />
<br />
There are a few different types of things you might be doing in the routes so here are a few examples of how to pass the errors.<br />
<br />
<script src="https://gist.github.com/envman/6e23e597d6f8d02887b7c204aac0ce07.js"></script>
This one just handles synchronous code that throws errors.<br />
<br />
<script src="https://gist.github.com/envman/190e8f1a425757848b8f55f74bac0863.js"></script>
In this case, we see an example of how to pass callback based errors.<br />
<br />
<script src="https://gist.github.com/envman/89a0efa8d26343b4da6acc938af02106.js"></script>
And then moving into promises, as long as we make sure that we pass the error to next, the error handler middleware will be activated.<br />
<br />
More on error handling strategies to come!<br />
<br />
<img alt="project coding GIF" height="359" src="https://media2.giphy.com/media/dlMIwDQAxXn1K/giphy.gif" width="640" />robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-25482226580774751872018-08-10T09:48:00.000+01:002018-08-10T09:48:13.344+01:00async/await in node.js: error handlingSo, let's have a quick look at async await error handling!<br />
<br />
<script src="https://gist.github.com/envman/ae996e72532a972b4ac82f8ff7e4ef6d.js"></script>
Like last time we are wrapping our code in a self-executing function so we can use the async keywords.<br />
<br />
To handle errors in async functions we use a try-catch block like we normally would in synchronous code. You can see from the example that a rejected promise comes out of our catch block.<br />
<br />
<script src="https://gist.github.com/envman/6ae15295e490ac6b67af503264668b72.js"></script>
As we know from previous posts a promise will be rejected if reject() is called or an error is thrown inside of the promise.<br />
<br />
<script src="https://gist.github.com/envman/d98bbc80e770a3b962f2ef5d367af8ef.js"></script>
Also if you throw an error in an async function this results in a rejected promise. So you can see now how it all fits together, any promise rejections or errors thrown result in the catch block being used.<br />
<br />
<script src="https://gist.github.com/envman/3515c795cc5abd307e91e49923bb195b.js"></script>
Just worthy to note that non-awaited rejected promises will not trigger the catch block but will put up an unhandled promise rejection error.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com3tag:blogger.com,1999:blog-1575614895289975380.post-79871949337157591652018-08-09T12:44:00.000+01:002018-08-09T12:44:15.015+01:00async/await in node.jsAsync await is a syntax that makes your asynchronous code look more like synchronous code, it is basically some nice syntactic sugar built on top of Promises.<br />
<br />
<script src="https://gist.github.com/envman/77b776ea2972ab7fa4d9d87eb4491f5f.js"></script>
You just add the async keyword to your function and or expression and that method will now return a promise! You can then use the await keyword to get the result of the promise!<br />
<br />
<script src="https://gist.github.com/envman/d13b54aaf5b02eeaeb4202777ef95ffb.js"></script>
One thing to note is await can only be used inside of an async function, so if you want to execute the code just in a file you need to wrap it in a self-executing function.<br />
<br />
<script src="https://gist.github.com/envman/8fa8445f06e791d02e4d1de35f8d68fb.js"></script>
I know what you're thinking, "This is great so I can stop writing those weird promises now right?", well no. Though you can quickly create synchronous-looking code that returns promises in either resolved or rejected state.<br />
<br />
<script src="https://gist.github.com/envman/4c2a6d2c35b4fa0d84685cfbd50714be.js"></script>
This does not allow for the handling of asynchronous code that is not promise based inside of your function.<br />
<br />
<script src="https://gist.github.com/envman/4428f12c40622263354e2df104e2beaa.js"></script>
Unfortunately, this will not work as the function will just return a promise that has undefined or no value. To get around this we need to wrap our callback code in a promise as before.<br />
<br />
<script src="https://gist.github.com/envman/a5640262d944a9e0d49ff7575d043771.js"></script>
This can now be used in an async function!<br />
<br />
<script src="https://gist.github.com/envman/efb98cc157249d0b7a4ee61f7b5dd471.js"></script>
You can also make good use of util.promisify to help you with this!<br />
<br />
<script src="https://gist.github.com/envman/0207bb6728f5b56960fa5aeeb756b4c1.js"></script>
Just remember it will only work for functions where the parameters match the node pattern of callback last and the callback starts with the error.<br />
<br />
<script src="https://gist.github.com/envman/886d8902b2f0e3f22b5be85b2bd9c6a2.js"></script>
You can see in this case that by defining our callback method to the node standard util.promisify happily wraps it in a promise.<br />
<br />
<script src="https://gist.github.com/envman/6aaec2e439c8cc6ae4cda04513f6059f.js"></script>
In this case, I removed the parameter passed to doTest() this results in a "TypeError: callback is not a function" error being thrown, which will be very confusing if you didn't write the callback code you are wrapping and it doesn't have very good error messages.<br />
<br />
More on async/await soon!robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-39307166897395040562018-08-08T12:16:00.001+01:002018-08-08T12:16:56.394+01:00Promises in node.js: nesting promise patternsJoin me for a little exploration in some patterns that can be used with promises, we will mainly play around with different ways to pass data through promise chains and how to get what you want out of the other end.<br />
<div>
<br /></div>
<div>
<script src="https://gist.github.com/envman/48da114ac308d3fd899ff56ef5ea4259.js"></script>
<div>
<br /></div>
<div>
<div>
Here we are loading the user information, then passing the id from that object to another two promises. The reason the two on the inside are nested is that they both need access to the user object. This also leads to another potential problem because the inner promises are executed sequentially, and in our case, they don't need to be.</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/envman/c53d334b7e9b788b9b0440b3d39afce7.js"></script>
</div>
<div>
<br /></div>
<div>
<div>
This solves the problem in a pretty neat way, we wrap the two inner calls together in a Promise.all() to get them to execute in parallel. Notice how we take advantage of array destructuring to pass in the results together, this is a very useful little pattern.</div>
<div>
<br /></div>
<div>
There may be a specific requirement for this to be changed into an object rather than an unwrapped array, in this case maybe you could wrap both calls in a method with a .then() map.</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/envman/29764dde4e81d6a285154e39eb58edf1.js"></script>
</div>
<div>
<br /></div>
<div>
<div>
It's up to you really where the different conversions and abstractions go, I'd advise being careful of having lots of little functions to wrap things up as it leads to code being hard to follow.</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/envman/d3da4f841010e3d08db95ce161c99cb7.js"></script>
</div>
<div>
<br /></div>
<div>
<div>
But what if we want to merge all of the data together into a single object, you can, of course, do this by nesting all the promises into one inner promise to share the data, but what if we are trying to avoid doing that?</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/envman/d3ccc67d9edc08a8226ef210b773eaf6.js"></script>
</div>
<div>
<br /></div>
<div>
<div>
In this case, we change all of the functions to take and return a context object that is updated by each function, this can seem a desirable way to do things but I would recommend against it. Firstly now every method isn't really a pure loading method its kind of a loadUserMessagesAndUpdateContext() method, while if you use this pattern lots I'm sure people wouldn't be too confused unless they hit issues with the way this is going to execute. If you look at my examples they will update the context object before they resolve. Most of the time this probably won't be a problem, but it could definatly give someone a headache.</div>
<div>
<br /></div>
<div>
Join me next time when we look at async/await!</div>
</div>
</div>
</div>
</div>
</div>
</div>
robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com3tag:blogger.com,1999:blog-1575614895289975380.post-41261196738229369762018-08-07T12:37:00.000+01:002018-08-07T12:37:25.811+01:00Promises in node.js: Helper functionsToday we will have a look at some of the cool helper methods provided by the native promise framework. The first couple are just quick helpers to create promises in different states.<br />
<br />
<script src="https://gist.github.com/envman/9de6f31bfe8d25b70a8ca0c6c2590f24.js"></script>
These methods quickly wrap values in promises of either resolved or rejected state. This will then execute the path that that promise would normally go down (i.e. .then() for resolved, .catch() for rejected).<br />
<br />
<script src="https://gist.github.com/envman/a1606d2cac4a7d2025e909d3ed223b13.js"></script>
In this example we use a made up httpGet function and pass in urls to get an array of returned data. The simplest way to think about Promise.all is that it takes an array of promises and returns a single promse that resolves when all of the promises in the array are complete.<br />
<br />
<script src="https://gist.github.com/envman/98d19b26b0e9364ada89b7194fac88f2.js"></script>
This helper is similar to all except as the name suggests it just returns the first one that completes, this could potentially be a way of implementing timeouts on things, I find myself using Promise.all() much more frequently, but still it is good to understand!<br />
<br />
<script src="https://gist.github.com/envman/5de5b6b870956e9cc9eb64d8b6552f14.js"></script>
Finally blocks are useful to help you close down resources no matter what happens.<br />
<br />
<script src="https://gist.github.com/envman/976424f597867fb01c9117cdfc0346df.js"></script>
Just a quick note to show that promises can have .then() put on them after they complete and the chain will still be executed. The reason for attaching this inside of another .then() was so that the eventloop would get a chance to fire before attaching the new one.<br />
<br />
More promises coming soon!robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-71912712149106931202018-08-06T14:13:00.000+01:002018-08-06T14:13:48.562+01:00Promises in node.js: Error HandlingContinuing on with the promise theme, let's have a look at error handling.<br />
<br />
<script src="https://gist.github.com/envman/a6a47ab074ab60961de5cc24d24c9d40.js"></script>
When executing this you will get a warning, that starts with:<br />
UnhandledPromiseRejectionWarning: This is a rejected Promise<br />
The warning also tells you that the error was not handled by a .catch() block.<br />
<br />
<script src="https://gist.github.com/envman/f51235049f1f9e5ac315dfc1ac5915a5.js"></script>
In this case we get a similar message: UnhandledPromiseRejectionWarning: Error: An error happened inside the promise, but not rejected.<br />
Both cases can be handled by adding a catch block to the code.<br />
<br />
<script src="https://gist.github.com/envman/c6d31c632b8564345c42952e8e3bb889.js"></script>
To add an error handler we just add a .catch() block to the end of the promise execution chain, if reject is called then the parameters passed to reject will come out of the catch handler function.<br />
If an error is thrown then the error will come out of the handler function. So we can see how .catch() blocks are very useful but you need to be careful about nesting promises inside of each other.<br />
<br />
<script src="https://gist.github.com/envman/287019266686a98925b69a92870ad748.js"></script>
In this case, we get an unhandled promise rejection message again, because the .catch() block will not pick up the rejected promise. To solve this we can do a couple of things, in most cases, you can just bubble the promise out of the inner .then() block.<br />
<br />
<script src="https://gist.github.com/envman/dd2df1b72185dffed3340cd60ade84ca.js"></script>
The error handling will now work at a higher level because the promise chains are connected. But sometimes we may want to do some additional handling first.<br />
<br />
<script src="https://gist.github.com/envman/f8802f7355d49244d650efd176ef3aad.js"></script>
It is still important to connect the chains by returning the inner promise chain or the outer handler won't fire. When a promise is returned from inside a then block the new promise state will be dependent on the inner one.<br />
<br />
<script src="https://gist.github.com/envman/517bd73a3c2b3d0901f3db9b6ac24493.js"></script>
In this case, the inner error block will fire but not the outer, as no error was thrown. And the outer .then() block will still fire!<br />
<br />
<script src="https://gist.github.com/envman/2159f6e9b58a2c39868b409eaa3042c7.js"></script>
So if you do want to execute both catch blocks make sure to throw an error in the inner one, how much of a good practice this is I'm not sure but it helps to understand what state the promises are in.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-39267112670312133942018-08-05T10:44:00.000+01:002018-08-05T10:44:25.291+01:00Promises in node.jsAs mentioned in my callbacks post some of the issues with callbacks can be solved with promises. Also once you understand how the core promise methods work you can use a few tricks to make your code look much nicer.<br />
<br />
<script src="https://gist.github.com/envman/82a2579f598515a952dbe99d38f74905.js"></script>
Firstly we execute our promise returning method "writeFile", this returns a promise that we can call .then() on. The function that we pass into .then() will be executed once the asynchronous code has finished executing much like a callback.<br />
<br />
<script src="https://gist.github.com/envman/468e2e141aa1e04be0121e799df67df9.js"></script>
In this example we can see that data can be passed from the promise to the .then() function and then passed into another promise, but doesn't it look like we are going down the same too much indenting route in the code?<br />
<br />
<script src="https://gist.github.com/envman/c4dc58fcba11bdecbd3e2fd1a65d6ccb.js"></script>
One of the cool things about promises is that they pass whatever is returned out of a .then() function out as a promise. Let's take a look at a couple of examples to make this clear.<br />
<br />
<script src="https://gist.github.com/envman/d35f7ac186c4209c1946e771f680d2e9.js"></script>
We can see in this example that the text "TESTING" is returned out and wrapped in a promise, the second .then() function will receive this data as a parameter.<br />
<br />
<script src="https://gist.github.com/envman/036e53c8898e86723f2bc4c6159bfdfb.js"></script>
In this example the second block returns another promise already so that promise will be returned from the first .then(), allowing the second .then() to trigger after the first completes. This is a simple yet powerful mechanism that helps us to write more straight line code around promises and mix asynchronous and synchronous then blocks in a way where the intent of the flow is clear. And it should all work nicely as long as we remember to return the promises out of the .then() expressions.<br />
<br />
One of the other things you will quickly need to do is create your own promises, you can wrap callback code in promises to make your life easier.<br />
<br />
<script src="https://gist.github.com/envman/8a96c5221eeb99a9a32be97d5c5b2780.js"></script>
In this example, we have a function that creates a new promise wrapping the fs.writeFile function, in its simplest form a promise is an object that takes an expression with 2 parameters, resolve and reject. We can execute asynchronous code inside of the block and just make sure to call resolve when we are completed or reject in case of error/failure. In this case we implement a callback on fs.writeFile that calls resolve when completed.<br />
<br />
<script src="https://gist.github.com/envman/86a7503e6d786184e06c1b316e8c7ae1.js"></script>
We can also use util.promisify(), this function will take a method with a callback and return the same method wrapped in a promise. It should definitely work for all of the core node functionality and probably most other things, but be cautious with non node functions (from libraries), as they could implement a different signature and not work.<br />
<br />
<img alt="awesome old school GIF" height="270" src="https://media0.giphy.com/media/Z6f7vzq3iP6Mw/giphy.gif" width="640" /><br />
<br />
So yeah that's pretty awesome! more on promises coming soon! and probably some async/await!robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com1tag:blogger.com,1999:blog-1575614895289975380.post-83607331541689346972018-08-03T10:09:00.000+01:002018-08-03T10:13:25.631+01:00Callbacks in node.jsDealing with asynchronous execution is a big part of writing code nowadays, there are many different ways languages allow you to do this but I am a big fan of how node.js does it. Your code in node.js only executes in a single thread, this makes reasoning about it so much easier and it uses some simple mechanisms to make a single thread more than enough to run the average web server.<br />
<br />
To do this any slow running operation you start will be run on another thread that you have no control over.<br />
<br />
<script src="https://gist.github.com/envman/a05c4ca4e8448c6437bdba6d0740a3ac.js"></script> This would output "I happen before it is finished" before outputting "finished writing file". This is caused by the callback function being queued for execution on the main event loop as soon as the operation completes. One thing to be careful of is keeping your execution running, this will block anything else from happening in your code.<br />
<br />
<script src="https://gist.github.com/envman/537e89fb62d04d4e3597174170b02357.js"></script> Because this loop keeps executing it stops the event loop from being able to run anything else and basically takes the web server down until you release control. This is why you should avoid using the sync methods that are provided by many APIs as they will block the event loop while they run.<br />
<br />
So this is all well and good, and one of the things I like about this approach is it is reasonably simple to understand and get started using node.js. But as time goes on you will probably find some problems.<br />
<br />
<script src="https://gist.github.com/envman/4b8152a61982f45bdee7d28e3eb1cf35.js"></script> You can already see the way that this is going, most people call it callback hell, when the code just keeps indenting as you get more callbacks, and you can manage this by wrapping some of the functionality into your own functions but it can still be hard to manage. Especially when most of your functionality is orchestrating other slow-moving parts.<br />
<br />
<script src="https://gist.github.com/envman/7738012bbaf83b8e1fc74835282b549b.js"></script> This doesn't really solve the problem in my opinion as it starts to make the flow of the code very hard to follow jumping around the file and also dealing with lots of callbacks. There is one other problem with the basic callbacks that you will most likely hit before long.<br />
<br />
<script src="https://gist.github.com/envman/9ccddfd506037e751ea5f22bada7a91d.js"></script> While this is better than some of the ways I have seen to achieve this, it's not particularly friendly to follow and it also executes once at a time, which is great if that's a requirement but not so good if it isn't.<br />
<br />
I am by no way saying you shouldn't use callbacks, they are very simple and easy to get started within a new node.js application, but quickly you will probably want to start looking into promises (I'll cover these in a blog soon!). Personally, I usually start off with callbacks and migrate to promises when needed, slight inconsistencies don't worry me too much in this case, but as time goes on I do find the promise interfaces nicer for most things and am mostly using them.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-47505736411339410232018-08-02T17:55:00.000+01:002018-08-02T17:55:07.003+01:00Dictionaries for constructing condition-less logicWhile I don't recommend removing all conditional logic from your systems, lots of conditions can often be a sign in my mind that the design does not match the problem being solved. Normally I would expect freshly refactored code to be lower on conditional logic and for it to increase heading up to the next run of the design being refactored.<br />
<br />
<script src="https://gist.github.com/envman/9a45db871e8cf1c272d8444f324706b4.js"></script>
<br />
We can start to move the conditional code out into a dictionary, this makes it more open closed principle compliant and less risky to add new functionality to the system. It's great if you've identified that this area keeps changing.<br />
<br />
<script src="https://gist.github.com/envman/0dc62a44440954482f564467ba2779cc.js"></script>
<br />
We can take this further and create registration methods so that if we are in a shared piece of code the upper levels or consumers of the code can add additional functionality that will have access to things defined at a much higher level.<br />
<br />
<script src="https://gist.github.com/envman/cdccaf8b030e97cb6d1d3fe098ab863e.js"></script>
<br />
In the long run, some of these patterns can be used with care to reduce the amount of confusing logic that is all in one place. so that the core flow of the application is easier to understand.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-57863763363113427112018-08-01T19:05:00.001+01:002018-08-01T19:05:14.227+01:00Blogging UpdateSo you may have noticed that my blogging has increased significantly of late, last month I made more blog posts than I had in the previous 4 years. It has been really rewarding and has lead to a lot of interesting conversations with people about some of the topics posted.<br />
<br />
Why the sudden increase? Well, I have always wanted to blog more but really struggled to get them out. There were many draft posts in different states of completeness sitting unpublished on my blog, so it was time for a different approach, first downsize posts to make them easier to write, then try to develop a daily habit of shipping a post every day. By reducing my size and quality goals I have managed to produce a lot more content and I can work on increasing the quality over time. Is it really quality if no one sees it?<br />
<br />
I've managed to quickly resurrect some of the half-written posts and break them into small series as well by just changing my mindset to at least ship something every day. And while I managed most days last month I started on the second and I did have one day where I was ill and didn't write a blog.<br />
<br />
It's also strange because I watch quite a bit of fun fun function and he posts every Monday morning and I remember watching one of his videos and it was quite short and I was like man, way to phone it in. But now I think about it people who make this kind of content are just people that are successfully maintaining a habit of regularly producing content, they're not superheroes! Sometimes it's hard to keep up, like today for example when I'm posting in the evening due to being very sleepy this morning!<br />
<br />
Well, hopefully I can keep this going for a bit and maybe settle on a slightly different schedule over time, produce and reflect!robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-40033037302094824112018-07-31T10:26:00.001+01:002018-07-31T10:26:11.529+01:00Tools and why we use themJumping on a new sexy tool/fad are we?<br />
<br />
<img alt="hugh laurie queue GIF" height="516" src="https://media1.giphy.com/media/zWngqI4fOr7iw/giphy.gif" width="640" /><br />
<br />
We constantly need to reevaluate the state of play, tooling, practices and languages are constantly changing around us. So assuming what we thought was good yesterday is still good can be a massive downfall, in all honesty, there's a pretty good chance that it wasn't ever good.<br />
<br />
I can definitely see a trend where generally when we think something is good we overdo it, next thing you know it is a best practice and we do it everywhere, not just where it makes sense.<br />
<br />
I remember switching to dependency injection and suddenly we decided it should be in every class, everything should be injected. Instead of deciding on a case by case basis to use it when we needed to test we just did it everywhere. It results in us not using our brains and just running on autopilot, perhaps we should always fall back to thinking about what things are good for.<br />
<br />
I also saw an interesting talk lately on why we shouldn't always use microservices, the main point seemed to be that we should start off with a single application and change to microservices when they would benefit the project, though I completely agree with this I think it can be hard to change to microservices when you haven't done them before so perhaps mandating a practice for a specific application from the start is ok if one of the main goals is to learn the practice.<br />
<br />
So my point really is to identify the benefit of a tool or practice and be careful in this identification. I would say architectural i.e. SOLID style reasoning is not good enough to justify a tooling. For example, if you say that dependency injection is for decoupling of dependencies please can we ask what the purpose of the decoupling is. So I would say dependency injection is for allowing us to inject stubs (not mocks!! :/) at test time, so how about we just use it where we want to inject test things. Also with some restructuring just having the consumer pass in the dependencies seems much easier than using a dependency container.<br />
<br />
Maybe next time we are trying something we should also try a couple of manual alternatives and evaluate the differences to help us avoid practices that we can do without.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-44430695340839999372018-07-30T09:18:00.000+01:002018-07-30T09:18:11.320+01:00closuresClosures are great! When I first started coding in javascript I wondered how you manage to hide data in your objects... The answer closures!!<br />
<br />
Let's take a normal class (oh thanks ES6!)<br />
<br />
<script src="https://gist.github.com/envman/d30651ce52828393f5bba350212a2179.js"></script> Now how would we do the same with a closure?<br />
<br />
<script src="https://gist.github.com/envman/36e006dd0f268b8529e1ea57173b1b63.js"></script>
the factory function serves to store all the information inside of its closure when it is executed, so all passed in parameters are available to any functions on the created object. It also makes them inaccessible to anything on the outside. Elegant and simple, no extra syntax required.<br />
<br />
After using this pattern for a while in some applications I noticed that we were often only returning a method with a single function attached to it, in these cases is it even necessary to have the object?<br />
<br />
<script src="https://gist.github.com/envman/94509c667e383d3ae86801ce76ce0d84.js"></script>
In this example, we just return a function that can do the work. This is simpler and it also helps to make it so that the abstraction only performs a single task.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-29415217668242021332018-07-29T17:30:00.000+01:002018-07-29T17:30:35.384+01:00Test First PipelineSo we've gone from testing after the code has been merged to master to testing before it is committed and it's great. But I think we can go further, what I suggest is that we test before we develop, much like TDD, testers and the PO would design UI/Acceptance tests before it is coded. Then the tests are run before the code is merged, much like TDD this helps to guarantee the code is testable before it is created.<br />
<br />
This would also require stronger working between developers, testers and business analysts, hopefully resulting in a good working environment focused on quality. I think this mentality would also be good for teams, always thinking about how something is going to be tested and the impact on quality, as many times in development the issues arise because of one role not sufficiently supporting the others.<br />
<br />
The whole team can also decide on the scope that requires testing if there is to be any manual testing, what parts are likely to break etc.robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-21808493249169148192018-07-28T10:11:00.000+01:002018-07-28T10:11:15.775+01:00Sketchnotes<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-gq3dnK00hXY/W1wy9QBJ6fI/AAAAAAAAFr0/Or3c3WlfVo0kTw9K7rZsisuna8ebkIXuwCLcBGAs/s1600/37973431_10156563411515682_4519046666229121024_n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="900" height="640" src="https://1.bp.blogspot.com/-gq3dnK00hXY/W1wy9QBJ6fI/AAAAAAAAFr0/Or3c3WlfVo0kTw9K7rZsisuna8ebkIXuwCLcBGAs/s640/37973431_10156563411515682_4519046666229121024_n.jpg" width="360" /></a></div>
<br />robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-61154651841334257182018-07-27T09:15:00.000+01:002018-07-27T09:40:55.719+01:00Solo ProgrammingSolo coding is a new practice where a developer sits down and puts their headphones in and works completely on their own. This allows for higher concentration and individual focus levels just not achievable in group working! It means the team can output more work! Every developer can maximise their output!<br />
<br />
<img alt="han solo GIF" height="640" src="https://media1.giphy.com/media/gZXI7pNvN5AaY/giphy.gif" width="640" /><br />
<br />
Some developers dislike pair programming, it's not a bad sign on them. There are a lot of benefits to mobbing or pair programming. But I have days when it's just nice to put my headphones in and get on with stuff, maybe this is bad? I mean now I've gone and added less reviewed code that only I understand.<br />
<br />
The first step is to make sure that the developers understand the benefits of shared work, it may seem slower at first than solo work but after you get some practice you will find that the work starts to speed up and you become way more efficient working together. Also, it is about the best way to share knowledge and reduce risk as a team. When a single person writes or works in an area they are the only person that knows that area, meaning that others will misunderstand and potentially cause issues when working there. Knowledge gaps can lead to failures and big problems with people having time off.<br />
<br />
I would suggest that to start we begin by timeboxing the pairing activity, its a completely new way of working and it will take some time to get used to. Also, you must remember to strictly follow the rules, pair programming or mobbing is not just sitting around the computer working together, there is a strict format to follow. One person should be on the keyboard and the other(s) should be navigating, this means the person on the keyboard should follow instructions from the navigator(s) not just get on with the work and explain. The navigator(s) should be telling the driver what to do, they are in control at this point, follow this with extreme discipline! Also, the position should swap regularly, I recommend 5/10 mins then swap.<br />
<br />
So give it a go trying to follow the rules properly, after a while you can adjust the numbers if you want, and start extending the time pairing. I still have mixed feelings about how much I enjoy group work, but I can clearly see it is a benefit, so trying to find a good balance of doing it regularly feels important, also I read that some companies are trying to vet out people who don't like pairing in the interview process nowadays...<br />
<br />
<br />robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-4560994972816942512018-07-26T09:40:00.000+01:002018-07-26T09:40:08.338+01:00Test Software Like AIIt seems to me that in the future the role of an application developer in many markets will revolve much less around describing the functionality of an application in code and much more in training AI systems. This splits the developer's role into two main areas, creating the training data and testing that the AI is performing tasks correctly. As often the solutions that the AI may come up with are hard to understand and reason about we may not even bother. If we can test it well enough we just test that it achieves all of its goals.<br />
<br />
So why don't we start testing applications in this way now, it's just an extension of where we are naturally going with Test Driven Development. If we write the tests from a black box point of view that confirm the application or significant subsystems function as desired. If we test well enough then the tests become much more valuable than the application its self in many ways. The application can be completely rewritten and we can guarantee that it works in as many cases as possible.<br />
<br />
It seems very likely that as AI allows us to develop systems much faster and with much less understanding of how the system actually functions that the role of dev-testers will become the main job in a development team. These engineers will still code, building tools to help them test the applications as I believe it is very hard to make a generic test framework for all applications that can function as well as specifically designed tooling that takes into account the domain.<br />
<br />
The machines are coming, let's make sure they do what we want :)<br />
<br />
<img alt="terminator 2 thumbs up GIF" height="640" src="https://media3.giphy.com/media/7TtvTUMm9mp20/giphy.gif" width="547" />robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0tag:blogger.com,1999:blog-1575614895289975380.post-91921646334532479842018-07-25T09:57:00.001+01:002018-07-25T09:59:00.310+01:00Asking QuestionsThe goal is a really great book, not only do you get the lean approach to running a business but also the approach that the mentor character takes to teaching is one that seems really effective. He always answers questions with more questions forcing the main character to really think about what the answers to his own problems are.<br />
<br />
<img alt="elephant questions GIF" height="400" src="https://media0.giphy.com/media/l0IyjeA5mmMZjhyPm/giphy.gif" width="300" /><br />
<br />
Upon further research this approach appears to be based upon the Socratic Method, by Socrates who was born in 470BC. So why have we adopted it so little? I guess it because it is very hard to retrain yourself to ask questions instead of give answers, maybe there is something satisfying in appearing smart because you know the answer. But there is surely more value in asking the correct questions, the learner will start to develop better analytical patterns to follow when they have questions, and this should free up time for the teacher as much less explanation is required.<br />
<br />
But what questions should you ask as the teacher, one question suggested by a colleague of mine when a junior team member approaches them is to ask them what they have tried so far, this seems to be a good starting point. From here do we ask them a question to highlight the area they should be looking at or do we ask a question to get them to think about the different areas the problem could be in. I would suggest the latter as surely the goal of teaching is to make the student independent of the teacher.<br />
<br />
<img alt="unimpressed reading GIF by SpongeBob SquarePants" src="https://media2.giphy.com/media/WoWm8YzFQJg5i/giphy.gif" /><br />
<br />
Time to read some plato I think!robert gillhttp://www.blogger.com/profile/13112663459410504309noreply@blogger.com0