tag:blogger.com,1999:blog-73921327588725487212024-03-12T18:02:22.058-07:00Squaredi.com: Coding, Craftsmanship, and TechnologyDrew Shefman, a Houston based Software Craftsmen / Interactive Developer / Architect and Instructor, shares his discoveries as he navigates the intricacies of the ever changing software development worlddShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.comBlogger74125tag:blogger.com,1999:blog-7392132758872548721.post-56792192514497383212022-04-13T07:39:00.008-07:002022-06-15T07:12:14.525-07:00Going Solar<p>So, we just installed solar panels on our house and I have some info to share. We purchased it ourselves and did not go through a co-op. </p><h3 style="text-align: left;">TL;DR:</h3><p></p><ul style="text-align: left;"><li>When you are talking to the different sales people (and do talk to several of them) the company mostly likely does 1 of 4 things and subcontracts the rest. Choose based on what you are most concerned about.</li><ul><li>They make the panels or equipment</li><li>They do the installation</li><li>They manage the financing</li><li>They provide or manage the electricity<br /><br /></li></ul><li>The loan is different than other loans you are familiar with. As of 2022, there is a 26% government rebate (hopefully it will be extended), that the loans incorporate. The loan is recalculated after 18 months, because they expect that you pay the entire rebate into the loan when you get it, if not, then you monthly amount will go up for the remainder of the loan term (20 years). If you frequently owe federal taxes, you need to take that into consideration, as part of the rebate would reduce the amount you owe, but then if you don't pay that full rebate into the loan, the monthly payments will go up. <br /><br /></li><li>The amount of wall real estate around the electric meter is significant. Be sure to take that into consideration. (See photos at the bottom)</li><ul><li>Given our real estate AND the base flood elevation, it was really tricky on how to arrange the 3 additional panels around the meter. <br /><br /></li></ul><li>Of the many reasons to get solar, if you are trying to account for power outages, you will be paying the most. If you can deal with a tiny (hopefully) number of days without power even when the sun is out, or can solve that in another way, you can pay a lot less. <br /></li><ul><li>We opted for a portable duel fuel gas generator. It is manual, and will power the fridge and maybe a few outlets with the propane tanks that we normally keep on hand for the grill. </li><li>In short, if there is a power outage and full sun, we are getting limited power from a small generator, not the panels. <br /><br /></li></ul><li>Unless you buy a battery, your solar panels will be tied to the grid. If the grid loses power, so do you. Batteries are really pricey ($13K) at the moment. As far as I know, there is no way around this, as the excess energy needs a place to go. <br /><br /></li><li>Once the panels are installed, expect several delays before you get fully operational. </li><ul><li>First, Centerpoint needs to grant Permission to Operate (PTO), which is when you can actually literally flip the switch to enable the panels. This takes a few weeks to a month. </li><li>Then after that, Centerpoint needs to acknowledge that you are producing excess energy. We are still in this phase. I've heard it takes about 2 months. But so far my utility bill only reflects what I'm consuming (at night), not what I've produced, so my utility bill for the first 2-3 months will not be zero (even though I should be overproducing). </li><li>I don't know yet if when Centerpoint does acknowledge the credits, if it is retroactive or starts at zero. In other words, since we turned on the system in March, I don't know if in May (hopefully) when this happens, if we get credit for all of the sunny non-AC days of March and April, or if May is day 0. <br /><br /></li></ul><li>Pay close attention to how your utility company handles net metering. You will likely need to switch to a new company. Green Mountain, for example, which I'd been with forever and thought would be really good, only will buy from you what you buy from them per month. This means that you can't build up credits in the spring for the summer. I'm now with Rhythm. <br /><br /></li><li>I would recommend <a href="https://www.astrawatt.solar/">Rising Sun Solar</a> (recently renamed to Astrawatt) or <a href="https://www.gosunpro.com/">Sunpro</a>. <br /><br /></li><li>According to HCAD, the panels raise the price of the house, but DO NOT raise your taxes. <br /><br /></li></ul><span><a name='more'></a></span><span><!--more--></span><h3 style="text-align: left;"><span style="font-size: medium; font-weight: 400;">==================================================</span></h3><h3 style="text-align: left;">Story:</h3><div><br /></div><div>Starting after the Feb freeze of 2021, I wanted a solution for power outages. I knew that I didn't want a full house generator. There were many reasons for this, but mainly I didn't like the idea of paying $15K for something that if I did use, might be once or twice per year. Additionally, solar has always been appealing - freedom from the utility company, to help the environment, and to reduce future energy costs (especially knowing that after the freeze, electricity costs are going to have to increase).</div><div><br /></div><div>I had a friend who worked at a solar company and so that was the first sales person I talked to. It was a medium-hard sales pitch. It was also weird because I had to sign a couple of forms to get the quote, and then I was getting emails from the company like I had already signed up. Anyways this first company was a national solar provider, but really they specialized in the loan and financing. </div><div><br /></div><div>That being said, the offer was pretty good. It was 0% interest and the panels were fully warrantied. The monthly payment was equal to my current average monthly bills. Speaking of average monthly bills, I was using the data from 2020 and 2021, so it was 100% at home meaning that the numbers were likely already the max that they would ever be. </div><div><br /></div><div>The research and reviews were not great, but the sales person dismissed them as not local given that they were a national company. Still, it was an uneasy feeling. Then I researched the employee reviews of the company, both from my friend and through sites like Glassdoor - also not great. </div><div><br /></div><div>Then I got several recommendations from Facebook and other sources to talk to a specific person, Gage Mueller at <a href="http://gosunpro.com/">Sunpro</a>. He was a fantastic resource and I would highly recommend him. He gave me all of the info that I wanted without the sales pressure. He actually refused to work with me. After inspecting our roof and learning that it is an all metal roof, he said that he and his company don't have the experience or the ability to install into our roof. I REALLY appreciated his honesty. He also said that he would remain available to me to answer any other questions and to help evaluate other companies. Which he was true to his word and I talked to him several times as I was evaluating other companies. </div><div><br /></div><div>Gage referred me to Paul Oxidine from <a href="https://www.astrawatt.solar/">Rising Sun Solar</a>. Paul was very similar to Gage and was (IMHO) honest and authentic. That is ultimately who we went with and I would recommend them (They are installers). Paul said that they DID install in metal roofs, but it was difficult. He said that his prices would likely be higher than others because of the roof complexity. I appreciated this honesty as well. </div><div><br /></div><div>I called two other solar companies, but they did not rank higher than Rising Sun. <br /><br />I reached back out to Rising Sun and the first company I talked to asking about their metal roof experience. I also asked if they had any metal roof customers I could talk through. The first company said they had experience, but ultimately couldn't connect me with a reference. Rising Sun was able to prove both their experience and had relevant customers I could talk to. </div><div><br /></div><div>Rising Sun's president also called me and talked to me about the installation process, the complexities of the metal roof and reassured me that he, himself, would be onsite during the install. </div><div><br /></div><div>Then just to be extra positive, I reached out the the roof manufacturer and got documentation on how they would install panels into their product. I sent this documentation to Rising Sun's president and he reported that that was exactly how they planned on installing the panels. </div><div><br /></div><div>So at this point I'm fully sold on Rising Sun, now I just need to figure out the options and financing. We opted not to get the battery because frankly we would need 2 to power the house and the extra $26K pushed us past our budget. Hopefully battery prices come down in a couple of years and we can add them then. We needed the 2 batteries because we have 2 AC units and the pool pump, in addition to our normal usage. This also means we needed a bunch of panels (57 to be exact - ugh). </div><div><br /></div><div>Solar is definitely expensive in the short term, though everything seems to indicate that it will save money in the long run. (Ask me in 10 years :)). We were exploring the different financing options and reached out to our financial advisor. They actually recommended that we self finance the solar from our VUL (Variable Universal Life) savings. </div><div><br /></div><div>This basically means that we loan the money to ourselves. (We are very fortunate to be able to have this option and I'm mentioning it in case others who read this have similar abilities as something to consider). We are already contributing monthly to this savings account, and we will be upping that amount to what would be the monthly payments if we financed. By loaning it to ourselves, there is no interest nor specific payback timetables. </div><div><br /></div><div>The main downside to this plan, is that since this essentially coming out of our life insurance pot, that if we die before we repay it, there is less benefit in the pot. But at that point we are dead and it sucks all around! </div><div><br /></div><div>We signed the contract and started the process. Rising Sun comes out with a few people to measure inside and outside the attic. They run real numbers (versus the guess that the sales person does) and determines the best place to put the panels. They then develop all of the permits and engineering documents. </div><div><br /></div><div>I warned them that our HOA was likely going to be the biggest issue, but I was shocked when it sailed right through without comment. I've heard that there are Texas laws that limit the HOA's ability to refuse but it has be proven that the locations are the most efficient for sun collection. </div><div><br /></div><div>The hardware and panels were delivered and sat in our driveway for a few days because of poor weather conditions. It took 2 days to install the panels, then an additional 2 days for the electrician to wire everything up. (The electrician could have done it in one, but he didn't ask me before installing the new panels and he had originally put them below BFE, so I had them move them above the flood line).</div><div><br /></div><div>HCAD actually came by during the installation. The panels raise the price of the house, but DO NOT raise your taxes. That is a cool benefit. </div><div><br /></div><div>Then we had to wait for the Permission to Operate. Once we got that, I got to throw the huge switch and turn on the system. That same day I switched to Rhythm Electric because they are promising unlimited never expiring credits. That means that when I'm overproducing in March, I should have plenty of credits for the summer. At least that is the hope. <br /><br /></div><div>As I said, I'm not sure that will actually work out this year because of the acknowledgement of credit from Centerpoint, but eventually the goal is zero utility bills. <br /><br /></div><p></p><div>BTW, if you switch to Rhythm because of me, use this referral link: <a href="https://www.gotrhythm.com/raf?referralCode=iXUxnM7tbk&utm_medium=raf">https://www.gotrhythm.com/raf?referralCode=iXUxnM7tbk&utm_medium=raf</a>, and it will give BOTH of us $100 credit. </div><div><div><br /></div>I'm happy to answer any questions either via comments or direct messages. </div><p></p><div><br /></div><span><!--more--></span><span><!--more--></span><h3><span style="font-size: medium; font-weight: 400;">==================================================</span></h3><h3 style="text-align: left;"><span>Photos: </span></h3><p></p><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdiIGBx5Jg3a7x31i3n0eI4CNAKbUlJSlePcJSNHmbNdYyls2sHhhrJJM6TmpMyrAAvmvVyZn4CDTa8628SZ6yezu5OSiguDBn6_FLPNGY8OQcg1VNZzJ6OvJs3g169VoueLCW8uob3fyPJM_NXrNWiDN2XsQsjYxhP22B_lfVGGLcjgRRxT6hfIOY_g/s1280/2022-02-1.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdiIGBx5Jg3a7x31i3n0eI4CNAKbUlJSlePcJSNHmbNdYyls2sHhhrJJM6TmpMyrAAvmvVyZn4CDTa8628SZ6yezu5OSiguDBn6_FLPNGY8OQcg1VNZzJ6OvJs3g169VoueLCW8uob3fyPJM_NXrNWiDN2XsQsjYxhP22B_lfVGGLcjgRRxT6hfIOY_g/w519-h292/2022-02-1.jpg" title="Drone shot of our solar panels" width="519" /></a></div>Drone Shot of our solar panels. <div><br /></div><div><br /></div><div><br /><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf3Px_i2bVcFJsD214FC3fyS6WojiPTD0un1nDrt_ca18wLCrtzI0bFkZ03glshwHy2bt7yOib7F2r9uWZBuTlIAA_7SwMvkWb9Rnl45cJScWzhTBHhs5uRYzuIt-LpM1rj2tSVCVkN3NKPrxwq023fQnt1A3-FzM3awIPBlatk1PwqkWcc3JhiSJm3A/s4032/20220413_090301.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4032" data-original-width="3024" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf3Px_i2bVcFJsD214FC3fyS6WojiPTD0un1nDrt_ca18wLCrtzI0bFkZ03glshwHy2bt7yOib7F2r9uWZBuTlIAA_7SwMvkWb9Rnl45cJScWzhTBHhs5uRYzuIt-LpM1rj2tSVCVkN3NKPrxwq023fQnt1A3-FzM3awIPBlatk1PwqkWcc3JhiSJm3A/w480-h640/20220413_090301.jpg" title="Solar Electrical Components" width="480" /></a></div>Here are all of the electrical components (in purple) needed for just panels without the battery. </div><div><br /></div><div><br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwLlyJ8sfvaYOqXxRjFlMkti-CgAC3s1ohlo70DVDKQs1e-vZmAe3rJHfL08XTYf525eqFleap_10ayFw203EwS0zsCmgaV9PWxnQzVOJALNnjwFuXpVYsrFFNXh650aH0LU2X53BxeT-F3ilkrojK6CHv5FNvFzIb0JWk54DSDdG_Yb9uHn0cYiZmYw/s1616/Screen%20Shot%202022-04-13%20at%209.09.12%20AM.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="488" data-original-width="1616" height="149" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwLlyJ8sfvaYOqXxRjFlMkti-CgAC3s1ohlo70DVDKQs1e-vZmAe3rJHfL08XTYf525eqFleap_10ayFw203EwS0zsCmgaV9PWxnQzVOJALNnjwFuXpVYsrFFNXh650aH0LU2X53BxeT-F3ilkrojK6CHv5FNvFzIb0JWk54DSDdG_Yb9uHn0cYiZmYw/w493-h149/Screen%20Shot%202022-04-13%20at%209.09.12%20AM.png" title="Energy Graph" width="493" /></a></div><br /><div><br /><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p>Best part is seeing the graphs. Here is a fully sunny day in April. The blue is what I'm producing and the orange is what I'm using throughout the day. It is still cool enough that the AC isn't on. <br /><br /></p><h3><span style="font-size: medium; font-weight: 400;">==================================================</span></h3></div><div><span style="font-size: large; font-weight: 400;">3 month update</span></div><div><span style="font-size: large; font-weight: 400;"><br /></span></div><div><span style="font-weight: 400;">So far so good. I've paid $0 for 3 months. </span></div><div><span style="font-weight: 400;">In April, I earned $115 of credits. </span></div><div><span style="font-weight: 400;">In May, I used up $14 of credits, leaving me $101.</span></div><div><span style="font-weight: 400;">In Jun, I earned $10 in credits, so back up to $111.</span></div><div><span style="font-weight: 400;"><br /></span></div><div>So it appears like with the initial $115 boost from spring, I might be able to make it through summer with a +/- credit of approx $20 / month, but still not ever actually pay anything.... hopefully. </div><div><br /></div><div>For your own calculations, there are many charges and taxes and that you will need to plan to exceed. </div><div>Rhythm Base Charge<span> </span><span> </span><span> </span><span> <span> </span></span>$8.95</div><div>TDU Delivery Charge - Base<span> <span> </span></span><span>$4.39</span></div><div><span>TDU Delivery Charge - Energy<span> $51.10</span></span></div><div><span><span>City Sales Tax<span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> $2.12</span></span></span></div><div><span><span><span>PUC Assessment<span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> $0.34</span></span></span></span></div><div><span><span><span><span>Misc Tax Reimbursement<span> </span><span> </span><span> </span><span> $4.12</span></span></span></span></span></div><div><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> -------------</span><br /></div><div><span>Total<span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> </span><span> $71.02</span></span></div><div><span><span><br /></span></span></div><div><span><span>Basically this means that you need to overproduce by about $75 dollars. This is likely equivalent to about 750 Kwh or roughly 25 Kwh per day. </span></span></div>dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-18143121815802277642021-05-05T11:25:00.000-07:002021-05-05T11:25:13.077-07:00Safari Low Power Mode<p> Let's talk about the <a href="https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari" target="_blank">unclear documentation </a> of Safari's Low Power Mode. </p><p>Here are some steps to get started: </p><p></p><ol style="text-align: left;"><li>Log in to developer.apple.com</li><li>Go to https://developer.apple.com/download/more/</li><li>Download "Additional Tools for Xcode12"</li><li>Open "Quartz Debug" in the Graphics folder.</li><li>In the menu bar, click Tools -> Enable Quartz Debug. Then, Tools -> Show detached regions.</li><li>Your screen should now be tinted red. If your screen becomes normal color, it means low power mode is working.</li><li>In Safari, start playing a video (it should be red tinted)</li><li>Go to full screen and wait for the controls to decay. If there is nothing else on the screen other than the video it should be back to normal colors indicating that Safari is successfully playing in low power mode. <br /><br />(This might seem backwards, but low power mode is basically the idea that nothing on the screen is rendering other than the video. The the red overlay is rendering, then that is the indication that other non-video things are rendering as well.)</li></ol><div>Things you need to know if you are going to test or implement this: </div><div><ol style="text-align: left;"><li>You can't have multiple monitors connected.</li><li>It only works when the video is playing. If the video is paused, it will not be in low power mode. </li><li>The full screen element needs to have a `background-color: transparent`. Even though it is the default, it needs to be explicitly declared. The documentation says it needs to be `black`. This is wrong. </li><li>Parent nodes of the video node, up to the full screen element need to have no background-color defined or defined as transparent.</li><li>Other html elements that exist within the full screen element and on top of the video element need to have a display:none. Empty nodes will cause it to NOT go into low power mode. </li><li>It will fail to go into low power mode if the page has a warning or error that displays over the window, not in the console, even if this error is not seen in full screen mode. For example, "This webpage is using a significant amount of memory, closing it may improve performance". </li></ol></div><p></p>dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-18351022071575223742020-06-25T09:57:00.002-07:002020-10-16T05:53:13.473-07:00Incorporating an Agile Mindset as an Individual<h2>
The Other Way to Scale Agile: How you as an individual can incorporate an Agile mindset even if you org chart nodes disagree. </h2>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-d7aeead6-7fff-f2f4-d6e3-ecd1ba17a1cc"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Much of Agile focuses on the “team”, but Agile is a mindset and a mindset starts with a single person. Whether you are on a fully agile team, transitioning, or agile is not even an option, there are a number of personal practices that can help you become an Agile Practitioner no matter what your environment might be.</span></div>
<br /><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">You will first understand what are some good personal and background practices that are foundational as an Agile Practitioner. Then you will gather techniques for acquiring and understanding feedback both from your users as well as your team. Finally you will learn some practices for being a catalyst for collaboration and commitment</span></div>
<div>
<span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div>
<h3>
<span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Slides and videos</span></h3>
<div>
<ul style="text-align: left;">
<li><span id="docs-internal-guid-d7aeead6-7fff-f2f4-d6e3-ecd1ba17a1cc" style="font-size: 14.6667px; white-space: pre-wrap;"><span style="font-family: Arial;"><a href="https://docs.google.com/presentation/d/1pzDImghIn9FS_HNihxG4aOdvIBNTiU3RGR21NyI2X_Y/edit?usp=sharing" target="_blank">Virtual Agile Shift Conference</a> (6/18/2020)</span></span></li>
<ul>
<li><a href="https://www.youtube.com/watch?v=mYcMXVPL7pU&feature=youtu.be" target="_blank">https://www.youtube.com/watch?v=mYcMXVPL7pU&feature=youtu.be</a></li></ul><li>Houston Tech Fest (Virtual) (9/18/2020)</li><ul><li><a href="https://www.youtube.com/watch?v=7Y1ba37B_3Y&feature=youtu.be">https://www.youtube.com/watch?v=7Y1ba37B_3Y&feature=youtu.be</a><br /></li></ul><li>Unicom TestExpo and Agile and Devops Expo 2020 (Virtual) (10/16/2020)</li><ul>
</ul>
</ul>
</div>
</span></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-62733893964763285672018-04-19T23:00:00.002-07:002020-12-03T06:05:33.873-08:00Agile in 160 Billion Gallons: When Agile Principles Occur During A DisasterWhile the Agile concepts may sometimes be easy, the why's and how's are a little trickier to wrap your head around. I’ve unfortunately participated in three recent rising flood water events in Houston over the last three years. Employing my agile skills has had a profound impact on the "success of the project".
<br />
<br />
Their are some agile principles that are naturally occurring during a disaster. The "product" is protecting your home by saving your possessions. The backlog is all of your possessions and it is prioritized by how you plan on attacking it. Some examples might be most expensive to least, or from the floor to the counters.<br />
<br />
Some agile principals, like self organized teams or iterations are partially present. And some principals are rarely applied at all.<br />
<br />
The demo, retro, and sprint planning, tend to fall away during a crisis, but I assert that those are most important for a successful product, as they are core to the agile principles of transparency, inspection, and adaptation.<br />
<br />
Here are the full slide decks.<br />
* <a href="http://www.squaredi.com/presentations/FloodAgileHoustonTechFest.pdf" target="_blank">Houston Tech Fest ( 10/14/2017 )</a><br />
* <a href="http://www.squaredi.com/presentations/FloodAgile-V2.pdf" target="_blank">Agile Leadership Network Conference ( 04/21/2018 )</a><br />
* <a href="http://www.squaredi.com/presentations/FloodAgile-V2.pdf" target="_blank">Houston Tech Fest - Spring (05/05/2018)</a><br />
* <a href="http://squaredi.com/presentations/FloodAgile-PMI.pdf" target="_blank">Project Manager's Institute - Houston Conference (06/05/2018)</a><br />
* <a href="http://squaredi.com/presentations/FloodAgile-TechFest2018.pdf" target="_blank">Houston Tech Fest - Fall 2018 (9/30/2018)</a><br />
* Houston Scrum Masters Alliance (1/28/2019)<br />
* <a href="https://static.sched.com/hosted_files/theagileshift2019/1c/FloodAgile-2019.pdf" target="_blank">Agile Shift Conference (04/12/2019)</a><br />
* <a href="http://squaredi.com/presentations/FloodAgile-2019-2.pdf" target="_blank">Houston Agile Leadership Network (7/18/19)</a><br />
<a href="http://squaredi.com/presentations/FloodAgile-2019-2.pdf" target="_blank">* </a><a href="http://squaredi.com/presentations/FloodAgile-2019-2.pdf" target="_blank">Houston Tech Fest (9/14/19)</a><br />
<a href="http://squaredi.com/presentations/FloodAgile-2019-2.pdf" target="_blank">* </a><a href="http://squaredi.com/presentations/FloodAgile-2019-3.pdf" target="_blank">Houston PMI October Meeting (10/9/19)</a><div>* Houston PMI August Meeting (08/19/20)</div><div>* Vivit-Worldwide Virtual Community Days - Agile, DevOps, and Testing Conference (12/2/20)<br />
<br />
<br />
Video recording:<br />
<a href="http://usergroup.tv/videos/agile-in-160-billion-gallons-when-agile-principles-occur-during-a-disaster" target="_blank">http://usergroup.tv/videos/agile-in-160-billion-gallons-when-agile-principles-occur-during-a-disaster</a><br />
<br />
<br /></div>dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-25769835055471648912018-03-10T09:12:00.000-08:002018-06-14T08:00:02.456-07:00Creating our Flood PlanSo having flooded three times, and being an Agile-ist, I'm always trying to improve. This is the summary of my flood plan.<br />
<br />
After my first flood, I spent some time (almost all of my time) thinking through the choices I made "in the moment" and how I could improve. So I came up with a flood plan, in case I ever flooded again. 13 months later, I had a chance to implement the plan. The plan worked very well. I spent some more time thinking about it and have developed the following.<br />
<br />
Before diving into the plan, I need to set the context. When I'm talking about flooding, I'm talking about a rising water event. This is where there is a lot of rain and after some length of time (maybe several hours) that rain isn't able to drain away any more and starts coming into the house. This plan does NOT apply to storm surges or dam releases where the water rises into the house within minutes.<br />
<br />
First lets start with the objective: "Save my stuff"<br />
<br />
Saving my stuff is quite broad. Saving all of my stuff is not realistic. This is where I failed during my first flood. I tried to save everything, but only that didn't happen - much was missed. And the things that I did save, were not the most important. Clearly I needed to prioritize. Here are the ways that I can think of to prioritize the things to save in my house.<br />
<br />
<ul>
<li>Irreplaceable -> Common</li>
<li>Expensive -> Cheap</li>
<li>Useful -> Unnecessary</li>
<li>Floors -> Counters</li>
<li>Front of House -> Back of House</li>
<li>Nearest (to me) -> Farthest away</li>
</ul>
<div>
For me, after the first flood, ending up in a barren apartment with nothing to sleep on, nowhere to sit, and a pile of boxes that I was unsure of what was even inside them. I choose Useful -> Unnecessary would be our prioritization. This means I will save the beds, sofas and chairs first and the stuffed animals and Pokemon cards that litter the floor, would be last. </div>
<h3>
<span style="color: orange;"><br /></span></h3>
<h3>
<span style="color: orange;">
Step 1: Determine the prioritization</span></h3>
<br />
Now that I have my priority set, how do I go about saving my household. Beds, sofas, chairs and tables take up a lot of floor space. How do I get them off the ground and how high do I have to put them?<br />
<h3>
<span style="color: orange;"><br /></span></h3>
<h3>
<span style="color: orange;">
Step 2: Determine the minimum and maximum height</span></h3>
<br />
For us, we have a 1 ft flood plan, it worked quite well during the second flood, where we only had 13", but would have failed massively during Hurricane Harvey where we would have had 51". If I had actually looked at and understood my elevation, I would have seen that my BFE was 4' and I should have planned for that all along.<br />
<br />
(I say would have had, because we elevated our house the day before Harvey hit. We had been in the process of elevating since the 2nd flood, and were scheduled to lift 1 week later, so we were able to accelerate the actual date when Harvey was developing in the Gulf of Mexico.)<br />
<br />
Just listing out our beds, chairs, and sofas, I quickly realized that we didn't have enough "up-space". And if we used all of our countertops for those items, where were we going to put the second and third tier of stuff. We needed to create more "up-space".<br />
<br />
The sofa is long and more things can be stored on top of it, so lets start there. For us, the sofa can perfectly span the kitchen counter to the island. This takes up minimal countertop space and the bridge that it creates can hold more things.<br />
<br />
We also reasoned that we could bring in the outside chairs, which are waterproof, and then create additional "tables" using our doors. We took the doors off their hinges, using the chairs as the supports, and created bunches more up-space for our inside fabric chairs.<br />
<br />
The king size bed was tricky. It is too big and heavy (temperpedic mattress) to try to move to a counter top. We just have to lift the whole bed. We have a collection of cinderblocks that now live under the bed. We remove the mattress and boxspring, position the blocks next to the legs of the bed, then lift the frame on to the blocks, then replace the boxspring and mattress. Then the kids twin beds can fit on top of the king.<br />
<br />
After wading around thigh deep during the first flood, a friend asked me what I would have done if the water kept rising. At this time, I honestly hadn't thought about it. I didn't have a maximum water height in mind. Which in retrospect, is kinda terrifying. We now have an inflatable boat (with a power AND hand pump). We have also talked to our high neighbors and have arranged refuge in their house should we need it.<br />
<br />
<h3>
<span style="color: orange;">
Step 3: Define your constraints, then brainstorm around them</span></h3>
<br />
The plan is coming together well, but to lift the furniture every time it rains is a non-starter. We needed a plan that including timings that dealt with the fact that most of the rain events wouldn't actually flood our house. We want to avoid throwing out our backs if the water is not actually going to come into the house.<br />
<br />
<h3>
<span style="color: orange;">
Plan Requirements: Save the things based on our priority, yet be mindful of the saving effort and probability of actually flooding. </span></h3>
<br />
So our plan is broken down into phases to account for the Plan requirements.<br />
<br />
<h3>
<span style="color: orange;">
Phase 1: Clean up the counters. </span></h3>
<div>
<u>Timing: Anytime the forecast calls for heavy rain / storms</u></div>
<br />
Phase 1 involves cleaning the house. Clean off all of the counters and tables. Put away all of the stuff. No dishes in the sink, no homework on the table, no unfinished project laying about, no laundry in the hamper, no clothes / stuffies on the floor.<br />
<br />
Put away everything to where it is supposed to be. Clean and put away the dishes, do laundry, clean up all of the toys, put away all of the art supplies.<br />
<br />
The purpose of this phase is to prepare the house in case it floods. We found that during our first flood, we were trying to save things, but there was stuff everywhere on the counters and it made it difficult to clean as well as lift. We also discovered that when we did salvage what wasn't damaged by water, that similar things ended up being boxed separately. (For example all of the things that were in the dishwasher, ended up being boxed and stored totally separate from the rest of the dishes).<br />
<br />
If it doesn't flood, which is the most likely scenario, we have a clean house -WIN. If it does flood, we have created space to put things and have returned everything to its home so that it can be kept together.<br />
<br />
<h3>
<span style="color: orange;">
Phase 2: Prepare to lift</span></h3>
<u>Timing: Expected flooding event about to start OR water over the curb</u><br />
<br />
Phase 2 is preparing to lift everything, but not actually doing any "saving" yet. For us, this means that we gather the outside furniture under the awnings around the house and near the doors. They are still outside at this point, but they are moved from their normal homes to a point where we can dry them off and prepare them to come inside.<br />
<br />
We also gather the saw horses from the garage and the pile of cinderblocks and bring them inside.<br />
We pay close attention to the forecasts / data (weather.com, weatherunderground.com, bayou level monitors) to determine how far Phase 2 goes.<br />
<br />
We might determine that preparation is done at this phase, or we might determine that it is worthwhile to go ahead and get farther in the lifting prep work.<br />
<br />
Going farther would mean that we would first move the cinderblocks to the areas that they would be used. We would start stacking the cinderblocks near the furniture in about the same size or related to the feet or footprint of the item. The idea being when we go to lift (phase 3) that we could pick up the item and put it down on the blocks fairly easily. We are not actually lifting furniture at this point though (though moving cinderblocks is not exactly light work either).<br />
<br />
We would stop and check the data again. If it is likely that flooding will not happen, we stop here. Sure there is effort to move the blocks, but we haven't rearranged the house yet. It is easy to undo.<br />
If the data still indicates that flooding is possible, or our worry or PTSD is too high, we continue to build the platforms.<br />
<br />
Platforms consist of saw horses and outdoor furniture with doors spanning them. We will take the doors off the hinges and create spans between anything that makes sense. This could mean we span the saw horses, kitchen counter and island, dining room table and buffet, etc.<br />
<br />
Not only does this create a lot of up-space, but it could also save the doors if it does flood.<br />
<h3>
<span style="color: orange;">
Phase 3: Lift</span></h3>
<u>Timing: Flooding potential unknown / water past sidewalks</u><br />
<br />
I'd be remiss, if I didn't include my favorite sound engineer joke (it might be the *only* sound engineer joke). Why do sound engineers say "Check 1...2... Check 1....2...."? Because on "3" you lift. :)<br />
<br />
Start lifting, but follow your priority. We lift our beds and sofas first, then the chairs, then the rest of the furniture. After that we start pulling out lower drawers, things still on the floor, then lower shelves.<br />
<br />
I have strong spacial packing skills (I'm always in charge of the dishwasher and the ornament box :)). I make sure that I'm maximizing our up-space.<br />
<br />
NOTE: Anything wood will float! Free standing book shelfs are not safe place to put things, unless the bottom is weighted (also another good use for cinderblocks)<br />
<br />
At this point, if it doesn't flood, we feel good that we practiced our plan. I find that working the plan helps me tremendously with the PTSD. I might grumble (alot) about un-lifting the furniture, but I (and my wife) appreciate having had actions counteract the worry.<br />
<br />
The kids might or might not be able to help lift during this phase. If they are not able to lift furniture, have them take pictures..... lots and lots of pictures. I told my kids I want at least 50 pictures per room. Take 3 pictures from every corner into the room, then 3 more from every doorway. Take pictures of every shelf. Open up every drawer and take pictures. Take pictures of the art on the walls.<br />
Please note, you might have to coach them that they should be clear pictures, and not hold down the button as they literally run around the room creating 50 house tinted blurs.<br />
<br />
<h3>
<span style="color: orange;">
Phase 4: Water in the house</span></h3>
We found that phase 4 is an odd emotional time, as water is actually in the house. At this point we continue to lift the things that we have missed. Maybe we tackle the second or third shelves based on what the predictions are.<br />
<br />
We had left one leaf of the dining room table for the kids to hang out in where they are safe and dry. There they are on devices to their hearts content.<br />
<br />
This is also the point we, the adults, start taking pictures and notifying social media of our status. Inside the house, we would notice and record the areas that the water is entering as potential places to address in the future. This is also the time that we would call the insurance company, figure out our new temporary housing options, and connect with the contractor.<br />
<br />
I told the kids that I was going to teach them a bad word. FUUUUUUUUU...... they said they already knew it. I said, well now is the right time to use it.... and you have to hold onto the U and really draw it out. And don't say it in school.<br />
<br />
We discovered that during phase 4, we needed to lock our doors. During the 2nd flood, the water pressure forced an unlocked door open. For what it is worth, doors and walls act as a really amazing filter. The water, for the most part, is a lot cleaner if it has to work its way in, versus coming through an opening.<br />
<br />
We also discovered that phase 4 might involve slashing the carpets. During the second flood, all of our furniture was secured in an up-space, but some of those spaces were on carpets. As the water rose, air got trapped under the carpet. Then when we would walk through the room, that air bubble would travel to our cinderblocks and platforms. So we took boxcutters and slashed holes in the carpets so we wouldn't cause our furniture to fall.<br />
<br />
Finally depending on the data, we would start planning our abort procedure. We have not actually got that point yet during any of the floods, so I can only assume that we would blow up the boat and contact our neighbors.<br />
<br />
<h3>
<span style="color: orange;">
Phase 0: When we are not flooding</span></h3>
So for all of the normal times that we are not flooding, here is some of the things that we have done to prepare for the next flood event.<br />
<br />
<ul>
<li>Take inventory pictures of the house every 6 months and store them in the cloud</li>
<li>Bought a 5 person inflatable boat for the 4 of us and the dog</li>
<li>Bought a portable pump to be used to help empty out water from the house. We use it to help move pooling water around in our backyard as well</li>
<li>Bought a dehumidifier so that we would have one in case it flooded</li>
<li>Scanned all of our photos and photo albums and stored them in the cloud</li>
<li>Converted all of our VHS tapes to DVD and digital copies. Also stored in the cloud</li>
<li>Everything stored below 2 feet is in a plastic bin</li>
<li>Everything stored below 2 feet is not important to us or decently water resiliant</li>
<li>We have some waterproof kayaking bags should we need to keep things dry during an evacuation</li>
<li>Hired a plumber and made sure all of our area drains were clean and in full working order</li>
<li>Don't keep any extension cords or power strips on the floor any more</li>
<li>We have sealed up the places that we noticed the water coming through</li>
<li>We have 2 sets of waders so it is easier (drier) to walk around during the flood</li>
</ul>
<br />
<h3>
<span style="color: orange;">Collected ideas from others: </span></h3>
<div>
<span style="color: orange;"><div style="color: black;">
Here is a list of ideas that other people have talked about</div>
<ul style="color: black;">
<li>Make sure that (at least some) toliet paper is stored up high</li>
<li>Get life vests for the whole family (and pets). Rescue boats often don't have them and/or if you have to make your way to a neighbors house.</li>
<li>Move cars to higher ground, Uber home</li>
<li>Valet park at the airport (making your car their responsibility), rent a car with full insurance coverage</li>
<li>Empty buckets for make shift toliets</li>
</ul>
</span></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com2tag:blogger.com,1999:blog-7392132758872548721.post-27842687904543121122017-06-26T10:24:00.000-07:002017-06-26T10:24:54.543-07:00Fluent Conference 2017 - Personal Recap<div class="MsoNormal">
<h2>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: large;">Fluent Conference 2017 -- Personal Recap</span></span></h2>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
The following is my summary and experience of my time at O’reilly’s Fluent Conference on 6/21 – 6/23 in San Jose, CA.
This is not intended to be coverage of any of the sessions I went to, only an account of the relevant, interesting, and/or curious bits that I got from each interaction
</span></span><br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Ignite Talks: </span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 12px;">I enjoyed attending the ignite talks, especially since I was a runner up for presenting. The presenters were well rehearsed and did a great job in the rapid format that is ignite. I was able to take some notes on what I can do next RFP rounds to potentially get farther. </span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 12px;"><br /></span></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 12px;">One of the talks, which was particularly interesting was about communication and expectation settings</span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Good questions to ask: </span></span>
<br />
<br />
<br />
<br />
<li>“What happens after I say yes?” </li>
<li>“What happens if something goes wrong” </li>
<li>Most of life is setting expectations and these questions help manage that</li>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Lockdown: A security primer</span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">I always enjoy attending security sessions, It is always good to refresh your personal paranoia. Most of this isn't new, but there are some new attack vectors that I hadn't heard of before. For example the SSLStrip was new to me, as well as some of the easy client side attacks that are available now. </span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Apps are more complex, yet our security knowledge has remained relatively constant<br />
“Security is like insurance: You only know how good it is after there is an incident”<br />
Attacks are escalating in severity and the barriers to staging an attack are lower than ever]</span></span><br />
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Man in the Middle Attacks </span></span></li>
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Defenses: everything needs to be https, specifically TLS not SSL </span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">For man in the middle with SSLStrip, defense is Strict Transport Security (including subdomains) </span></span></li>
</ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Client Side Attacks </span></span></li>
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">NEVER TRUST ANY USER INPUT </span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">This includes styles </span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Opt in to software / libraries that do most of the user validation for you</span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Be very careful about your browser plugins </span></span></li>
</ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Embedded malware </span></span></li>
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Limit attachment types (and do more validation than just extensions) </span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Optimize and re-process all images (especially dumping non-visual info)</span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"> Do not permit arbitrary HTML input </span></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Whitelist content </span></span></li>
</ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Cross Site Request Forgery </span></span></li>
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Defense: CSRF Token with non-predictablity and per request configuration </span></span></li>
</ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Click Jacking </span></span></li>
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Defense: X-Frame-Options</span></span></li>
</ul>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span><br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Async in Js</span></span></h3>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">This was a fantastic review of the pros and cons about the different methods of async in JS. I did not know about Async/Await or Generators. </span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span></div>
<br />
<ul>
<li>Callbacks </li>
<ul>
<li>Cons: </li>
<ul>
<li>Pyramid of doom </li>
<li>difficult to decode</li>
<li>inversion of control </li>
<li>(Note: Chrome has an async button in dev tools for debugging )</li>
</ul>
</ul>
<li>Promises </li>
<ul>
<li>Cons: </li>
<ul>
<li>No cancellation </li>
<li>Lots of nesting </li>
<li>Inside of thennable is still complicated, </li>
<li>Too many libraries </li>
</ul>
</ul>
<li>Async / Await </li>
<ul>
<li>Built into JS </li>
<li>Looks synchronous but non blocking </li>
<li>Still not cancelable </li>
</ul>
<li>Generators </li>
<ul>
<li>Uses yield and next keywords </li>
<li>Easy to read – looks synchronous </li>
<li>Pause and cancellable</li>
</ul>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span><br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Keynotes</span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"> The keynote format had 5-8 mini sessions inside the keynote. The theme of the conference was "Build a Better Web" and obviously most of the keynotes focused on that. </span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<br />
<ul>
<li>Are we really taking advantage of the technology? </li>
<ul>
<li>“Whether we are CSS or JS we are united by our users” </li>
<li>On a screen, we are processing in the visual cortext, which means it drives out all other brain activity </li>
<li>Apple ear buds are more than headphones, it is the start of implantable computers </li>
<li>Could we interact without a screen? </li>
<ul>
<li>Could an always listening device (like Responsive Voice.js) give us a summary of the conversations of our day? </li>
<li>Or help give insight into our mood? </li>
<li>Could it make us better humans? </li>
</ul>
</ul>
<li>Building a culture of collaboration in devops </li>
<ul>
<li>Things I need to look into more:</li>
<ul>
<li>Atlassian Dev Ops Playbook </li>
<li>Team Help Monitor </li>
<li>Glitch.com is a focus on tools and the community, it allows for remixing projects for API and community </li>
</ul>
</ul>
<li>The unsexy pillars of the web:</li>
<ul>
<li> Security, Accessibility, And Performance </li>
<li>“You can’t fix what you can’t measure” </li>
<li>We live in a web bubble of privilege of speed, access, and availability. </li>
<li>“Data changes irreversibly into information can can not be extracted from the information”. It would be like asking “what were the dimensions of this melted ice cube” or “how much milk was used to make this cake” </li>
</ul>
<li>Accessibility is about software quality</li>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Functional JS Data Structures</span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Excellent description of how functional JS works, especially with immutable arrays. The presenter was super passionate about functional JS and was a joy to listen to. Most of the talk was defining fuctional data structures vocabulary</span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<br />
<ul>
<li>Perstistant data structures </li>
<li>Path Copying & Structual Sharing </li>
<li>Trie => retrieval tree </li>
<li>Bitmapped Vector Trie (32 bit branches are ideal) </li>
<li>Hash Array Mapped Trie </li>
<li>Libraries</li>
<ul>
<li>Immutable.js (sort of OOP) </li>
<li>Mori.is (more purely functional and based on clojure)</li>
</ul>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">14 ways to bounce a ball (through code)</span></span></h3>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">I had higher hopes for this session. Having taught Flash based animations for nearly a decade, and having left that scene a couple of years ago, I was hoping to get some intel on the tools that people are using to animate. Overall it was nothing more than a list of code based tools to animate. The presenter started out with a client created animation in Adobe Edge Animate, which of course has terrible, not maintainable output. So the presenter went on a quest to discover a better way to animate with maintainability. Ultimately despite the research, could not create the richness of a visual animation tool, and used the Edge Animate output with all of its inline unmaintainable ugliness. </span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">But for reference here is the list that he talked about. </span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span></div>
<br />
<ul>
<li>Browser </li>
<ul>
<li>Vanilla JS </li>
<li>Css Animations </li>
<li>SMIL – deprecated </li>
<li>Web animations API </li>
<li>HTML5 video tag </li>
<li>Animated Gifs </li>
</ul>
<li>Tools </li>
<ul>
<li>Greensock </li>
<li>Velocity </li>
<li>Jo.js </li>
<li>Anime.js </li>
</ul>
<li>Other </li>
<ul>
<li>Jquery Animations </li>
<li>P5.js </li>
<li>D3.js </li>
<li>Matter.js </li>
</ul>
<li>Animations Paradigms </li>
<ul>
<li>Math (equations)</li>
<li>Physics </li>
<li>Flipbook </li>
<li>Keyframes</li>
</ul>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">CSS WTF</span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Being a CSS novice, this was a great session to learn some of the less used features of CSS. I especially liked the alternative (better) option than important. </span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<br />
<ul>
<li>CSS supports counting, and could be used for counting errors </li>
<li>UI selectors that are not common </li>
<ul>
<li>placeholder-shown </li>
<li>user-error </li>
<li>indeterminate (checkbox w/ slash) </li>
<li>read-only </li>
<li>read-write </li>
<li>Smell: use of important </li>
<ul>
<li>Instead of important, use multiple class decorations </li>
<li>.disabled.disabled is stronger than .disabled </li>
<li>#theirWidget#theirWidget doubles the weight of the selection </li>
</ul>
</ul>
<li>CSS supports blendmodes</li>
<li>CSS supports shapes </li>
<ul>
<li>Clip-path (shape or SVG) </li>
<li>Shape-outside is the HTML container shape for word wrapping </li>
</ul>
<li>CSS supports masking </li>
<li>CSS “Material Design Icons” </li>
<ul>
<li> Font-family: “Material Icons” </li>
<li>Transforms words as icons </li>
</ul>
<li>CSS as a modernizer with @supports</li>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Schema First Development with GraphQL</span></span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">I have heard around the office about our GraphQL, I didn't know much about it, so this was an excellent primer. </span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span>
<br />
<ul>
<li>GraphQL provides an intermediary interface contract between the front and backends </li>
<li>Better then REST because it reduces round trips and simplifies maintenance and provides only the data the client needs </li>
<li>It is a specification not an implementation </li>
<ul>
<li>Schema with strong types </li>
<li>Query schema </li>
<li>Results </li>
</ul>
<li>Requirements </li>
<ul>
<li>Hierarchical </li>
<li>Product centric </li>
<li>Strong types </li>
<li>Client specified queries </li>
<li>Introspective </li>
</ul>
<li>“Prioritize the developer experience”</li>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Keynote Day 2</span></span></h3>
<br />
<ul>
<li>Diversity and Inclusion Post mortem </li>
<ul>
<li>10 years and $500M invested and virtually no improvement </li>
<li>What went wrong </li>
<ul>
<li>We have not defined good outcomes </li>
<li>We have not created any methods of accountability </li>
<li>Not measuring inclusion, retention, promotion, or equity </li>
<li>Not monitoring all intersections </li>
<li>Too much reliance on Unconcious Bias Training </li>
<li>Not responding well to reports of harassment </li>
<li>No safe methods to speak up </li>
</ul>
</ul>
<li>You can’t get comfortable on the web </li>
<ul>
<li> Best photo on slide of whole conference =><div class="separator" style="clear: both; text-align: center;">
<a href="http://cdn.designrulz.com/wp-content/uploads/2011/12/designrulz-sofa-21.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="660" height="187" src="https://cdn.designrulz.com/wp-content/uploads/2011/12/designrulz-sofa-21.jpg" width="320" /></a></div>
</li>
<li>You don’t need to know everything, but make sure you know your foundations well</li>
<li>why-learing-to-code-is-so-hard:</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQKVcO09ck8XCZMKZ9McRFtpnm9Jf6x1WqS-iDAai6DuYrQzzRx6LO62keax-BrYdlzkgjb4D1U3neNhJUsuPH82r1-SvNSTTLa4W7y1wYCj4pj3QCtPlNoRUgYsb_dMGSe-SKLD31oUBw/s1600/coding_is_hard_confidence_competence.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="660" data-original-width="1001" height="420" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQKVcO09ck8XCZMKZ9McRFtpnm9Jf6x1WqS-iDAai6DuYrQzzRx6LO62keax-BrYdlzkgjb4D1U3neNhJUsuPH82r1-SvNSTTLa4W7y1wYCj4pj3QCtPlNoRUgYsb_dMGSe-SKLD31oUBw/s640/coding_is_hard_confidence_competence.png" width="640" /></a></div>
<li> On Community and Dev </li>
<ul>
<li>For humans communication is everything </li>
<li>Technology isn’t neutral </li>
<li>Commuinities break from lack of ability to deal with conflict </li>
<li>Commuity is the thing shared with the person you like least </li>
<li>Community is a group organized for mutual survival of their ideas </li>
</ul>
<li>Frustrations </li>
<ul>
<li>We are repeating the same ideas that were had at the dawn of the computer age, we have better implementations and new names, but the ideas are the same </li>
<li>“Don’t frustrate your users” </li>
<li>“Never underestimate mobile” </li>
<li>Embrace good ideas </li>
<li>Don’t take tech as a goal – tech is tool </li>
</ul>
<li>Progressive Web Apps </li>
<ul>
<li>This is the new buzzword, means app like experience in a mobile browser </li>
<li>Note: Lighthouse is a chrome canary option in dev-tools</li>
</ul>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Accessibiltiy testing:</span></span></h3>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">There was a heavy Accessibility (a11y) theme. It is nice to know that there are many automated testing tools for it. </span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span></div>
<br />
<ul>
<li>You can automate 30-50% of a11y issues</li>
<li> Npm install <span style="font-family: Courier New, Courier, monospace;">axe-core</span> for unit testing a11y in interaction / focus API, text alternatives, and ARIA states</li>
</ul>
<br />
<hr />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">
</span></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">Source Maps demystified</span></span></h3>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;">This was a deep dive into source maps. It was interesting discovering how they work. </span></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: 9pt;"><br /></span></span></div>
<br />
<ul>
<li>“JS is the assembly language of the web” </li>
<li>To keep maps secure, you can change the domain (last line) of a source map to vpn or localhost</li>
</ul>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-44955631819478663042016-04-13T14:28:00.002-07:002016-09-23T17:50:18.984-07:00Agile simulations - lego game<span style="font-family: "times" , "times new roman" , serif;">I teach an introductory class at University of Houston. This semester I did half technical and half soft skills (like Agile). </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">Given that I have a 3 hour class, I had the ability to try out the Agile simulation using legos ( <a href="http://www.lego4scrum.com/">http://www.lego4scrum.com/</a> )</span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">I had introduced agile to my class, but didn't go into any depth about Scrum or any of the other flavors. We basically had a conversation about if you were going to spend a lot of money on something that you were unsure about the final result (like a full sleeve tattoo), what steps would you go through to ensure that it matched your expectations. </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">All of this saying, they were not familiar with actually implementing agile or scrum. </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">I brought in a huge tub of my kids legos and set them in the middle of the class. I also brought 8 smaller storage containers that would allow the students to take scoops of legos back to their desks / work area. </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">I introduced the project explaining that we were going to be building a lego city, <i><b>my</b></i> lego city, and that I recommend that they break into small groups of 3-5 people (class of 25, although about 50% decided to not show up), and rearrange the furniture as they saw fit to prepare to build the city. </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">While they moved a couple of desks to sit on the floor, they generally <span style="color: red;">used this time to come scoop up containers full of legos to take back to their spots</span>. Meanwhile I covered the "land" with paper. I informed them that this paper was were the city was to be built and that for certain things, like roads, it was okay to draw them on the paper rather than make them out of legos. </span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">Then I introduced the things that I wanted in my city. I had, in my head, organized them by potential teams, but I never mentioned that to the class. I also intentionally didn't mention the acceptance criteria unless asked. </span><br />
<ul>
<li>Living: </li>
<ul>
<li>4 x 1 story homes </li>
<ul>
<li>Must have a window </li>
</ul>
<li>2 x 2 story homes </li>
<ul>
<li>Twice the size of a 1 story home </li>
</ul>
<li>Apartment </li>
<ul>
<li>3 stories, outside stairs </li>
</ul>
</ul>
<li>Recreation </li>
<ul>
<li>Park </li>
<ul>
<li>Trees </li>
<li>Playground </li>
</ul>
<li>Stadium </li>
<ul>
<li>Open roof </li>
</ul>
<li>Zoo </li>
<ul>
<li>One animal and enclosure </li>
</ul>
</ul>
<li>Business </li>
<ul>
<li>TV station </li>
<ul>
<li>Satellite dish or Broadcast tower </li>
</ul>
<li>Retail shops </li>
<ul>
<li>4 doors, each shop a different color </li>
</ul>
<li>Hospital </li>
<ul>
<li>Has a red plus on it </li>
</ul>
</ul>
<li>Education </li>
<ul>
<li>Elementary school </li>
<ul>
<li>Has a fence </li>
</ul>
<li>University </li>
<ul>
<li>Looking down on the top of the univeristy it should look like UH </li>
</ul>
</ul>
<li>Worship </li>
<ul>
<li>Religious symbol on it </li>
</ul>
<li>Infrastructure </li>
<ul>
<li>Power station </li>
</ul>
<ul><ul>
<li>Wind turbine (ie propeller) </li>
</ul>
<li>Waste water treatment </li>
<ul>
<li>Visible Pipes </li>
</ul>
<li>City Hall </li>
<ul>
<li>Dome on top </li>
</ul>
<li>Transportation </li>
<ul>
<li>Mass transit </li>
<ul>
<li>8” and 6+ wheels </li>
</ul>
<li>Dedicated bike lanes </li>
<ul>
<li>Barrier from cars </li>
</ul>
<li>Roads </li>
<ul>
<li>Drawn + 1 car </li>
</ul>
<li>Airport </li>
<ul>
<li>1 plane + terminal<br /><br /></li>
</ul>
</ul>
</ul>
</ul>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">I wrote each item on sticky notes, and used <a href="http://www.netobjectives.com/files/books/lasd/TeamEstimationGame.pdf">Team estimation game</a> to size the stories. (Think bubble sort). <span style="color: red;">We were about 60% of the way through (when we got to the university), that they started to ask about what I was expecting for the university. </span></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Since we had been sizing the stories as we went, we decided that we needed to start over. This time through we talked about the acceptance criteria before they determined left, right or same for the sizing. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Once all of the stories were grouped and positioned, I assigned Fibonacci numbers to them for the points. We had 1,2,3,5,8,13,21 and 50. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">I then organized the stories into a priority order. (I wished I had taken a picture of the final priority order before doing sprint planning). Meanwhile I had told the class to figure out if they were going to represent themselves as the separate teams, or as the company as a whole and to determine what they think is a good number of points to take on for the first sprint, which was 8 minutes.</span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"> We had 4 minutes for sprint planning, where the class, having decided that they were one company (instead of 5 teams) choose the items from the backlog that they were going to deliver for the first sprint. (<span style="color: red;">They completely ignored the priority order and choose what they wanted to work on, including the lowest priorty highest point story</span>). Also somewhat independently,<span style="color: red;"> some of the students had already started building, while others where choosing the stories from the backlog.</span></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><span style="color: red;"><br /></span></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">We started our first 8 minute sprint with a 106 point commitment. When the bell rang, there was nothing on the "land", so they got zero points. They were pretty disappointed, because they didn't realize that their structures needed to be on the table by the end of the sprint. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">We did a 4 minute retrospective, where again 5-8 students participated and another 4 minute planning, <span style="color: red;">the others continued building</span>. The planning was essentially moving over all of the unfinished stories, but they did add another 3 point story. Sprint 2 started with a 108 point commitment, but many of the structures were "done" and on the land within the first couple of minutes. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">The different groups, not surprisingly didn't talk to each other, and using the single story house as a scale reference, the "3 story apartment" was about 1/3 the size of a 1 story house. The hospital was about 1/2 the size of the house. The stadium, (the lowest priority and highest points), was done and used up a significant amount of lego bricks (that they would want for the next round). </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Sprint 2 ended with 96 points of the 108 awarded. The Sprint 2 retro <span style="color: red;">was largely ignored as everyone just kept building</span>. One person participated in sprint planning. They didn't move any of the unfinished stories over, but they did add 2 more stories. Ultimately they ended up committing to 6 points but completing 46. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Here is a photo of the finished city.</span></span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5qC73IViyqgBsRY9mFK7VJeZtUQZVOI2t2xt9ZHQ3QaTh14g7U5zGkwl8Rt7pBxk4Ea3G2VJ_bHc-y8PNrhUPagqgVFWm4x8CwtqZhn8XGwsIBC41H5D5jQcLStKvYRPhKjTfZCZgHpGo/s1600/20160411_200037.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5qC73IViyqgBsRY9mFK7VJeZtUQZVOI2t2xt9ZHQ3QaTh14g7U5zGkwl8Rt7pBxk4Ea3G2VJ_bHc-y8PNrhUPagqgVFWm4x8CwtqZhn8XGwsIBC41H5D5jQcLStKvYRPhKjTfZCZgHpGo/s640/20160411_200037.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Front L to R: Water treatment, power station, place of worship, university, stadium, hospital, airport<br />
Back L to R: zoo, elementary school, playground, 1 story house, tv station, 1 story house, 2 story house, apartment</td></tr>
</tbody></table>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">From the debriefing after the last sprint, here is what the students said were issues, especially after talking about some of the things in red from above: </span></span></div>
<div>
<ul>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">knowing the scale of the buildings</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">not knowing what the other groups were working on </span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Initially there was no talking, but it really improved towards the end when the groups started working together</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Pain point: What does the client expect to see</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Pain point: Client Priority</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Pain point: Dimensions / scale</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Pain point: 8 min sprints were stressful</span></span></li>
<li><span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Pain point: looking for resources / running out of resources</span></span></li>
</ul>
</div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">We talked about how they were overall more interested in building (playing with the legos) and less interested in understanding the clients needs. We talked about how they were also skipping the planning, which helps communicate expectations to the client, as well as the retro which would help them improve the internal processes. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">We then talked about variations and improvements. Interestingly enough most of them expressed that even though there were improvements that could have happened in the delivery of the exercise, they valued the mistakes that they made as it were, and ultimately decided that I should not add any more explanation or details the next time around. </span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;">Overall, it was an incredibly useful exercise and discussion around teamwork and communication with the client. </span></span></div>
<div>
<span style="color: #444444; font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="color: #444444; font-family: "times" , "times new roman" , serif;"><span style="line-height: 18.4px; white-space: pre-wrap;"><br /></span></span></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-41575461251423488932015-01-14T07:53:00.002-08:002015-01-14T07:54:33.418-08:00Treadmill desk as a software developer - injurySo a couple of days after my last post, I did have a treadmill related injury.... sort of. It wasn't cringe-worthy youtube kind of injury. It wasn't even an injury that was ON the treadmill.<br />
<br />
I was turning left to go into my closet and something BAD happened within my calf. It was crippling and I could barely put weight on that leg for two days. I used a lot of RICE (Rest, Ice, Compression, Elevation) and was able to start bearing weight again.<br />
<br />
My theory is that being on the treadmill, is that given it is a very straight and even surface for such long durations (10+ miles) and low impact, that I have been over developing my "walk straight muscles". So when I went to turn a corner, my now weaker "turn muscles", were literally squeezed out of place by my others.... It is my theory anyways.<br />
<br />
Some loose proof that I have that supports this, is that while I was recovering, I was acutely aware of variations in the ground, unevenness, and different textures.<br />
<br />
So now that I'm recovered and nearly able to to 10 miles again, I'm spending more time on the treadmill walking sideways. I'm also stretching mulitple times a day, using foam rollers and hard massage balls, and making sure that I spend more time off the treadmill and outside on the un-even sidewalks.dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-52541828492705128012014-12-17T08:45:00.001-08:002015-01-14T07:54:33.423-08:00Treadmill desk as a software developer - 3 monthSo we've been going on three months now. I'm able to walk about 30K (~14 miles) steps at least twice a week without feeling too bad. I've killed my tennis shoes that I bought during the summer, so I guess one side effect is that I'll be going through shoes much faster now.<br />
<br />
Things I've noticed:<br />
<br />
<ul>
<li>There was an online conference, that I was watching while I was working. This was great, but given that I was already switching between 2 engaging contexts, I didn't notice that I was walking, and I over did it again (37K steps, 2 days in a row before I noticed what was happening - I guess that means I'm getting better endurance). </li>
<li>On the day that my fitbit battery died, I wasn't motivated to walk until it was charged. Apparently I definitely want my steps to "count" </li>
<li>Grading my class assignments is MUCH more enjoyable while walking. Previously I could barely get through 1 without needing a break, now I can do them all in one "sitting"</li>
<li>There is a nice pile of dust, crumbs, etc that ends up on the mat at the back of the treadmill. </li>
<li>I hardly ever sit down anymore at work. Although I do still stop and stretch occasionally. As I try to hit 30+K once or twice a week. </li>
<li>I keep a set of hand weights on my desk for meetings, where I don't have to participate or take notes. </li>
</ul>
Overall I've lost 12 lbs (fluctuating wildly as we go through Thanksgiving and the holidays :))<br />
<br />
Still nothing but good things to say about the treadmill desk.<br />
<br />
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-88193818567799252262014-12-08T13:40:00.000-08:002014-12-08T13:40:32.668-08:00What I learned about coding from 5th gradersSo today I was mentoring / volunteering for Kolter's Hour of Code (<a href="http://www.code.org/">www.code.org</a>) and I got to observe 3 different 5th grade classes come through to try to program a visual game like Angry Birds or Lightbot.<br />
<br />
Just for context, both of these games involved sequencing directional puzzle pieces to perform a task. For Angry birds, you would move the bird towards the pig, and for Lightbot, you'd move the robot along a grid lighting blue squares.<br />
<br />
Not surprising nobody read the directions or prompts before diving right in. The part that I found interesting, was that very few would try to solve the problem in small steps.<br />
<br />
Nearly every pair (they were pair programming.... woot!) whether they read the prompt or not, tried to solve the entire puzzle before hitting play. It of course wouldn't work. Then they'd throw nearly the whole thing away and create another complete solution, which also wouldn't work.<br />
<br />
One of the things that I coached them on was to test often.... put down one or two commands and see where you are on the sequence. Basically to get faster feedback.<br />
<br />
So I'm curious as to where in life do we learn that we have to solve the whole puzzle at once?<br />
<br />
<br />dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com3tag:blogger.com,1999:blog-7392132758872548721.post-37920527723089315552014-10-07T08:00:00.002-07:002015-01-14T07:54:33.413-08:00Treadmill desk as a software developer - 1 monthLast month I posted my first week experiences on my treadmill desk: http://squaredi.blogspot.com/2014/09/treadmill-desk-as-software-developer.html<br />
<br />
Now I'll be moving into my one month review.<br />
<br />
My metrics are:<br />
Steps: 19.3K / day avg (darn weekends killing my average :) )<br />
Distance: 11 miles /day avg<br />
Max steps / distance: 31K / 14 miles<br />
<br />
So far I've lost 5 lbs. I'm stretching every night. I'm still taking breaks as needed, but overall I'm taking standing breaks instead of sitting breaks. I have to have some foresight into the evening plans though. If there is a kids soccer game where I'll be helping run around, or a dance lesson that I'm teaching, I will need to stop walking early afternoon and sit so that my legs are capable of the evening activities.<br />
<br />
I've noticed an increase in my endurance, where I've gotten 30K steps in a day a couple of times now and not been sore. I was also able to run the length of our street. (Note, I'm not particularly fond of running, but I was late for pickup from school. I was happy that I made it the whole street length, which is longer than I've run in recent past).<br />
<br />
Given that I'm farther from the ground in the office, both with standing, and with the small step up onto the treadmill, that fans alone don't cut it. I've had to lower the A/C to help keep the room comfortable.<br />
<br />
But the bottom line is that I'm loving it. I love being able to walk this much everyday and that it is not something "extra". I love that I can walk and work at the same time. I love that for a having a desk job, and working from home, that I'm lightly active to fairly active 6-8 hrs a day.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://content.screencast.com/users/dshefman/folders/Jing/media/ffc4c2a8-9b29-4166-ada4-819e11f35fc2/00000146.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://content.screencast.com/users/dshefman/folders/Jing/media/ffc4c2a8-9b29-4166-ada4-819e11f35fc2/00000146.png" height="524" width="640" /></a></div>
<br />dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-79069042934854221762014-09-09T08:32:00.001-07:002015-01-14T07:54:33.429-08:00Treadmill desk as a software developerBackground:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEilDkjK9zkXMDMQMGVlMIfo3BtgP8sQQTUDDRJ9GvN-HS_Huqz1Q0npzk0AX9f2HuswP-CYLKfoWWJCl2OAb6sQbzPi6oyzaHwgZYXzHNfp-MifKzuF58eTtbA118bGbDxGY0u436jVB5/s1600/20140903_132231.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEilDkjK9zkXMDMQMGVlMIfo3BtgP8sQQTUDDRJ9GvN-HS_Huqz1Q0npzk0AX9f2HuswP-CYLKfoWWJCl2OAb6sQbzPi6oyzaHwgZYXzHNfp-MifKzuF58eTtbA118bGbDxGY0u436jVB5/s1600/20140903_132231.jpg" height="320" width="240" /></a>I got a treadmill desk and will be writing my review from the perspective of a software developer who works from <br />
home.<br />
<br />
All metrics are tracked from fitbit, and just as a baseline, I average about 10K steps a day without the treadmill, but it has taken some dedicated effort.<br />
<br />
Day 1(Thurs)<br />
Based on the corner of the office that I put this in, I noticed that my overhead ceiling fan was less effective. I didn't break a sweat on the treadmill, I just needed to move some floor based fans to me. (FYI all of the computer equipment in my office gets warm, and instead of air conditioning the whole house, I use several fans in my office. )<br />
I found myself looking forward to meetings, especially those that I wasn't an active participant, so I could up my speed to around 3 mph. If I'm an active participant I found that 2 was about right for me.<br />
The treadmill is super quiet and my colleagues couldn't hear any background noise coming from my end of the call. Personally though, due to my own cognitive processing inability to separate noises, I found that I needed to move to loud speakers / headphones so I could hear better. But as I said, even though my hearing is fine, I know that I'm not able to separate sounds, so the treadmill, fans, and meeting was slightly indistinguishable for me.<br />
I didn't get bored as much, so I found myself talking less breaks. I also noticed that when I did feel like taking a break, there was a "stop" action. Literally pressing pause on the treadmill, was a more commitment to the break, then my usual get up to go to the bathroom or grab a snack from the kitchen. 23K steps - a little more than double my average up to that point<br />
<br />
Day 2 (Fri)<br />
Okay, I was a little stiff today. Clearly I pushed myself too hard. Today my pace was more around 1.5 for the whole day. I found myself inverting my day. Previously my breaks were to get up and walk around. I'd go to the farthest bathroom in the house, or to walk around and pace while eating my lunch to get more steps in. Today I found myself not doing those things. I even took a couple of breaks just to go sit on the couch for a couple of minutes. Then around 2pm. I couldn't walk anymore. I moved the laptop back to my desk and sat for about an hour or so. That night I had to stretch.<br />
<br />
Stretching isn't a bad thing, it means that I'm actually doing something with my muscles. 22K steps, which is still more than I was planning. I was hoping to only get to around 18K today.<br />
<br />
Thankfully a weekend is coming up, so I can start fresh again on Monday.<br />
<br />
Day 3 (Mon)<br />
Spent all day at 1.5 MPH. Still needed a significant sitting break around 2 pm. I've been drinking alot more water, because I also realized that I wasn't drinking enough the other days. It is really easy to overdo it, especially if you hit flow for a couple of hours. One tricky bug and 4 hours later I've walked nearly 6 miles. Unfortunately I hit 30K steps today. That is my all time high. I stretched a lot, but still woke up sore.<br />
<br />
Day 4<br />
Today I'm going to sit through the morning, and then start walking for my noon meeting. I only walked on the treadmill for 2 hours today, but since it was mostly a non-participatory meeting, I still managed to eek out 20K. In addition to stretching I had to use my wife's foot massager.<br />
<br />
Day 5<br />
So here is my new plan: I'll start the day sitting, then probably just after lunch I'll start on the treadmill. I'll put in an hour or two, then move the laptop to the desk. I'll leave the laptop unplugged and when I run low on battery, finish out the rest of the day on the treadmill. That should get me around 20K steps.<br />
<br />
Day 6:<br />
Throwing in some tech geekery. Given that I'm walking for a couple of hours and sitting for a couple of hours; I've got two separate external monitors that I'm hooking up to. The one on the treadmill is 25" and the one at the desk is a measly 17". It was very annoying that whenever I switched, I lost the locations of my windows. Be on the lookout for another blogpost regarding <a href="https://github.com/jigish/slate">Slate</a> for managing my Mac windows state across multiple monitor configurations. I just started with it today, and it is awesome, but will need to dive in more to be able to write up the post.<br />
<br />
Week 1: Metrics<br />
19.5K step average<br />
62 Miles<br />
<br />
<br />
<br />
Day etc.<br />
I'll do a followup post in a couple weeks, after a month or so of use. But as of today, I'm still following the sit in the morning, walk in the afternoon approach. This works well for me, that way I'm walking when I'm most awake / alert. I do need to stretch every night, which is not a bad thing. I'm feeling really good and haven't noticed a decline in productivity - actually I feel more focused when I'm walking. I have discovered that if I'm in the middle of something, and don't want to shift spaces from the treadmill to the desk, I'll sometimes just stand at the treadmill for a break. That works better than I expected. It is quiet enough to use at night with the kids asleep in the next room, but the kids informed me as they were going to sleep, that if I had my speed too high, that my steps were too loud (me walking, not the machine). I had one co-worker that could hear the treadmill (my steps) when I wasn't on the headset, but just on the computer, but when pushed, she said she really had to strain to hear it and it was very faint.<br />
<br />
<br />
<br />dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com1tag:blogger.com,1999:blog-7392132758872548721.post-87599657312110304422014-07-25T21:24:00.001-07:002014-07-25T21:24:47.341-07:00No Fluff Just Stuff - Lone Star Symposium Review<div class="separator" style="clear: both; text-align: center;">
<a href="http://nealford.com/images/nofluff-juststuff.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://nealford.com/images/nofluff-juststuff.gif" /></a></div>
The NFJS conference (July 2014 in Austin) was a perfect fit for me. It markets to a Java audience, but there was plenty of other topics covered. For me there was the technical Java track (immediately relevant to my current work), a functional programming track (future focused), and a soft skills track, which I found to be a pleasant and perfect balance. I'm definitely going to go back!<br />
<br />
<hr />
I started out with Javascript Design Patterns by <a href="http://twitter.com/prpatel">Pratik Patel</a>. He was particularly found of <a href="http://underscorejs.org/">underscore.js</a>, not only for the features set that it offered, but it's use in the mixin pattern, which he asserts is easier to maintain than the decorator pattern. I personally liked his example of this command pattern, which I'm showing below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNUOxaROrBZVBOofG5Mtw6CONW9rTc2waBYdWjwlQatvvSZRrkZrsc089kWmY_6FvkdI9xJUy1C6ylEw3LLvEXeIdb46xYvhkJBko64wfMzdZ1UbV7F2wwi7Te-nqrQLOaFG5nWsSOeCBq/s1600/commandPattern.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNUOxaROrBZVBOofG5Mtw6CONW9rTc2waBYdWjwlQatvvSZRrkZrsc089kWmY_6FvkdI9xJUy1C6ylEw3LLvEXeIdb46xYvhkJBko64wfMzdZ1UbV7F2wwi7Te-nqrQLOaFG5nWsSOeCBq/s1600/commandPattern.png" height="480" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br class="Apple-interchange-newline" /></div>
<hr />
Java memory by <a href="http://twitter.com/kensipe">Ken Sipe</a> was really deep, but it explained a whole lot of stuff that I never understood. Essentially the JVM segments the memory into 2 spaces, new and old. The idea being that for the most part, there are two types of objects occupying memory: the super short, like a message or request; and the incredibly long, like models which are needed for pretty much the whole time the server is up.<br />
<div>
<br /></div>
<div>
<a href="http://fishandbicylces.files.wordpress.com/2013/04/bring-out-your-dead.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://fishandbicylces.files.wordpress.com/2013/04/bring-out-your-dead.jpg" height="200" width="198" /></a>Given this idea, there is two main segments of memory, new and old. The new space is divided into Eden (brand new), SS0, and SS1, where SS* is a "survivor space" for not new, but not old objects. The old space is also divided into Old and PermSpace (Aha! that is what the JVM config -XXMaxPermSize goes). </div>
<div>
<br /></div>
<div>
(BTW, -XX is an experimental flag, while -X is standardized)</div>
<div>
<br /></div>
<div>
The idea is that GC is misnamed, it is not garbage collector, but really a garbage avoider. It actually never touches the dead, but does promote the living to the next level (from Eden to SS*, then to Old, etc) </div>
<div>
<br /></div>
<div>
There are two types of GC, major and minor. Minor happens only when Eden is full, which moves the living the the SS space, and resets Eden to write over the dead. Major GC affects all areas of memory and is slow and should be avoided if possible. The goal is a high morbidity rate in new space, and a very low morbidity in old space. </div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjHiPQ7mXVh0gEz24kHkSb7vtAPBnSndQr03DVnLRpdFX4ymQ2yQOhJme0tdIC-lqmUQSdoWIp-Ae0p9ayFtaB-ZRAo117tiE1eDrX2blnBSPhanyKBFjfWvTdUWxBIcVt0W4u0FDhBKYA/s1600/GCinEden.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjHiPQ7mXVh0gEz24kHkSb7vtAPBnSndQr03DVnLRpdFX4ymQ2yQOhJme0tdIC-lqmUQSdoWIp-Ae0p9ayFtaB-ZRAo117tiE1eDrX2blnBSPhanyKBFjfWvTdUWxBIcVt0W4u0FDhBKYA/s1600/GCinEden.png" height="320" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">After optimization</td></tr>
</tbody></table>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6q7644cCtBA9fErCq7XRke11Lay5OL5ZZudKiDP7RP5SxDOxJoEMsver3jn7WhSX9AYotrC7SdDIuAvQOj9MT_0NbK2YIBIPb7yT-dETsf7PmP7OS8yr_mTFineIJmXVPHc_hPhGErpyd/s1600/GCInOldMemory.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6q7644cCtBA9fErCq7XRke11Lay5OL5ZZudKiDP7RP5SxDOxJoEMsver3jn7WhSX9AYotrC7SdDIuAvQOj9MT_0NbK2YIBIPb7yT-dETsf7PmP7OS8yr_mTFineIJmXVPHc_hPhGErpyd/s1600/GCInOldMemory.png" height="320" width="242" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Before optimization</td></tr>
</tbody></table>
<br />
<div>
<span style="font-size: x-small;">XX:NewSize = 256m</span></div>
<div>
<span style="font-size: x-small;"><br /></span></div>
<div>
<span style="font-size: x-small;">XX:MaxNewSize =256m</span></div>
<div>
<span style="font-size: x-small;"><br /></span></div>
<div>
<span style="font-size: x-small;">XX:SurvivorRatio = 8</span></div>
<div>
<span style="font-size: x-small;"><br /></span></div>
<div>
<span style="font-size: x-small;">XX:PermSize = 32m</span></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Finally he gave a list of tool recommendations for Java tuning</div>
<div>
<ul>
<li>JPS</li>
<li>JSTAT</li>
<li>JMAP</li>
<li>JHAT</li>
<li>VisualVM* (his favorite, open source all in one troubleshooting tool)</li>
<li>VisualGC</li>
<li>MAT</li>
</ul>
<hr />
Functional JS by <a href="http://twitter.com/prpatel">Pratik Patel</a> was a great overview of the difference between functional and OO. Basically if comes down to that OO in JS is messy for the things that we need to do, and functional is a "recipe for simplicity". Again he talks about <a href="http://underscorejs.org/">underscore.js</a>, but this time we go deeper into<br />
<br />
<ul>
<li>composing</li>
<li>currying (special composition where first argument is the composed function</li>
<li>chaining</li>
</ul>
<div>
Transitivity is defined as "always getting the same result with the same input"</div>
<div>
And in general OO talks about nouns, where FUN talks about verbs. </div>
<div>
<br /></div>
<br class="Apple-interchange-newline" />
<hr />
Narcissistic Design by <a href="http://twitter.com/stuarthalloway">Stuart Halloway</a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-c00akOIz59_ie-D_50Pr7r8AyDOIDD6xOAfv0teAxlHjLvqJROOW4jQo3JEcFzad4TNd8yQgbDWI3gW1Zsdr_Yjil_H70IlerA7tP2WIMwYvIVJUwzvFs1gHh3Bewi50gI4vQynVXvf7/s1600/narcissisticDesign.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-c00akOIz59_ie-D_50Pr7r8AyDOIDD6xOAfv0teAxlHjLvqJROOW4jQo3JEcFzad4TNd8yQgbDWI3gW1Zsdr_Yjil_H70IlerA7tP2WIMwYvIVJUwzvFs1gHh3Bewi50gI4vQynVXvf7/s1600/narcissisticDesign.png" height="228" width="320" /></a></div>
<br />
<br />
Just as setting the context, Stuart is extremely passionate about Clojure and functional programming, so he generally exposes all of the evils of OO. And this talk is a humorous portrayal of that. Although if you listen with an open mind, putting aside your OO education, there are some interesting points of view to consider.<br />
<br />
The premise behind his talk is that by thinking only about "me", that you can add lots of complexity to the code base, all in the name of best practices. So here is a list of best practices that increases the complexity of the code base and makes it harder to share.<br />
<br />
<ol>
<li>Embrace setter methods : <br />Setters undermine the two best parts of OO: constructors and interfaces</li>
<li>Prefer APIs over data:<br />data forces decoupling, while API couples by temporality, language, mutability, semantics, and esoteric features</li>
<li>Start with DSLs (Domain Specific Languages)</li>
<li>Always connect, never enqueue</li>
<li>Create abstractions for information</li>
<li>Use static typing across subsystem boundaries</li>
<li>Put language semantics on the wire</li>
<li>Write lots of unit tests<br />He argues that once tests are passing, they tend to always pass<br />He also argues that generative testing would test more options then a handful of pathways</li>
<li>Update information in place<br />This practices comes from assumptions that memory / storage is expensive and resources are dedicated<br />It is not needed anymore and immutable data facilitates easy sharing, distribution, concurrency, access, and caching</li>
<li>Leverage context</li>
</ol>
One of the neat ideas was to learn some of the data languages like you would a programming language:<br />
<br />
<ul>
<li>avro</li>
<li>bson</li>
<li>csv</li>
<li>edn</li>
<li>fressian</li>
<li>hessian</li>
<li>java</li>
<li>json</li>
<li>kryo</li>
<li>protobuf</li>
<li>thrift</li>
<li>yaml</li>
<li>xml</li>
</ul>
<br />
<br class="Apple-interchange-newline" />
<hr />
Build your own technology radar by <a href="http://twitter.com/neal4d">Neal Ford</a> of Thoughtworks was by far the best / most inspiration session of NFJS.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVNFUkh1oFt_aGEKqIbEnBi8-AU4Vuoesc6_Pzlzz1fxq79jE0Sa9kFHqbB7Yoo0NmCOyyGrmFC2iEmDRaj7BvR7JP4gXBgj_PGNhRahjMNDL_AWFmW2P6FFh-i-ZkNzuspGuyfkHaBtSy/s1600/techRadar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVNFUkh1oFt_aGEKqIbEnBi8-AU4Vuoesc6_Pzlzz1fxq79jE0Sa9kFHqbB7Yoo0NmCOyyGrmFC2iEmDRaj7BvR7JP4gXBgj_PGNhRahjMNDL_AWFmW2P6FFh-i-ZkNzuspGuyfkHaBtSy/s1600/techRadar.png" height="374" width="640" /></a></div>
<br />
This is basically a snapshot in time by opinionated technologists. It is not comprehensive nor strategic. It is not a technology lifecycle assessment tool. It is ultimately a tool to montior ("keep on the radar") technologies.<br />
<br />
"You can't tell that the technology is stable or collapsing when you are on the inside"<br />
<br />
The interactive version is at <a href="http://www.thoughtworks.com/radar/#/">http://www.thoughtworks.com/radar/#/</a><br />
<br />
The rings of the radar from outer to inner are<br />
<br />
<ul>
<li>Hold - proceed with caution (notice there is no "avoid" category)</li>
<li>Assess - worth exploring with the goal of how it will affect you</li>
<li>Trial - worth pursuing on a low risk project. Get to know its strengths, limitations, and use cases</li>
<li>Adopt - finished a trial and found usage patterns</li>
<ul>
<li>Mason Razor: "I'll make fun of you at the pub if you aren't doing this"</li>
</ul>
</ul>
<div>
Neal strongly encouraged each developer to make their own radar. It is part of your knowledge portfolio, that needs to by managed. A simple API exsits for plotting one already at <a href="https://github.com/bdargan/techradar">https://github.com/bdargan/techradar</a></div>
<div>
<br /></div>
<div>
As far as evaluating new technologies, here is the litmus tests that were recommended:</div>
<div>
<ul>
<li>Testability</li>
<li>Integratability</li>
<li>Learnability</li>
<li>External references (books, blogs, conferences talking about it)</li>
</ul>
<div>
One of the best tactical / practical / immediately applicable comments was to write unit tests in a different language. For example write Java unit tests in Groovy. Given that tests are a form of overhead, there is a benefit to make it as efficient as possible. Besides you get to practice in a new language. </div>
</div>
<div>
<br /></div>
<div>
That night, I sat in the lobby of the hotel and attempted to re-write one of our test classes to Groovy. I ended up with 4 people pairing with me and it was SUPER simple. Within an hour, I had nearly the whole class in Groovy, and that was GDD (Google driven design, given that this was my first exposure to the language. </div>
<div>
<br /></div>
<div>
Neal also strongly recommends that COMPANYS create a technology radar as well. </div>
<div>
<ul>
<li>Gives you a platform for continual analysis</li>
<li>Unified message to non-technical but interested people</li>
<li>Excuse to get together to have an impassioned conversation</li>
</ul>
</div>
<br />
"The future is already here, it just is not evenly distributed" </div>
<div>
<br /></div>
<div>
Research shows that your next job comes from your weak links in your social network, instead of your strong links, like friends and family.<br />
<hr />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRhhMMhSFl30dpo5lN5VBYOiH0MYcEbSgI9CrYqEfbMZXQWnuyK1o_qOEjROEx2Gx0o0Hd9XPAesPxCAiU7ZFzpODBULNbCqSZXw9mkquDJLOtwUzJaVAr1nfplHtL89SFHwAnJFxzn86w/s1600/pitfalls.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRhhMMhSFl30dpo5lN5VBYOiH0MYcEbSgI9CrYqEfbMZXQWnuyK1o_qOEjROEx2Gx0o0Hd9XPAesPxCAiU7ZFzpODBULNbCqSZXw9mkquDJLOtwUzJaVAr1nfplHtL89SFHwAnJFxzn86w/s1600/pitfalls.png" height="176" width="320" /></a>The top pitfalls that lead to agile troubles by <a href="http://twitter.com/andy_painter">Andy Painter</a> was just a wealth of nuggets for my scrum master position.<br />
<br />
I enjoyed this presentation so much, that I even asked Andy to join me for lunch, so we could continue talking. I had several questions for him, and he provided great insight.<br />
<br />
<br />
<br />
<ul>
<li>Agile vs waterfall</li>
<ul>
<li> Agile is like flying an airplane, you continually have to course correct for wind, weather, traffic etc. Waterfall is like riding a train, where the plan has already been laid down for you to follow. </li>
<li>You can't say that Agile is faster than waterfall because they are not the same product. It is an apples to baseballs comparison. You can't assume that the finished agile project is anywhere near the same thing that would have been delivered via waterfall</li>
</ul>
<li>Scrum master</li>
<ul>
<li>Is about teaching</li>
<li>In order to teach, they need to be able to listen</li>
<li>Also needs to provide a safe place to fail, so that learning / improvements can happen</li>
</ul>
<li>Product Owner</li>
<ul>
<li>Available, knowledgeable, and empowered</li>
<li>PO as proxy should be a temporary position</li>
</ul>
<li>Learning from Failures</li>
<ul>
<li>True failure is not working through the challenges and giving up</li>
<li>"I welcome failure, not because I desire it as an ultimate end, but because I recognize that any true success must be born through some amount of failure. And because of this allowance, I expect my team to be better next year than they are today. </li>
</ul>
<li><a href="http://en.wikipedia.org/wiki/Cargo_cult">Cargo Cult</a></li>
<ul>
<li>I hadn't heard this term before, but it describe the condition of imitating actions expecting to produce the desired results. </li>
<li>For example, if a team says "we have a backlog, daily standups, and demos; therefore we are Agile", without understanding the why or treating style over substance, might be an example of the cargo cult. </li>
</ul>
<li>Standup</li>
<ul>
<li>If what you did yesterday, doesn't equal to what you committed to in yesterday's standup, that is an impediment</li>
<li>It isn't a status meeting, but at daily planning meeting</li>
<li>It is a layer PDCA cycle - Plan, Do, Check, Act</li>
<li>If "I'm working on it" for a couple of days, means that there isn't enough visibility.</li>
</ul>
<li>Velocity</li>
<ul>
<li>It is a PLANNING tool, not an accelerator</li>
<li>By definition it is a constant rate of motion</li>
<li>In retrospect, it should have been named "pace" instead, to take away the stigma that it can be throttled</li>
<li>Best stats is from the last EIGHT (8) sprints (3-4 months). This encompasses the average amount of stuff - vacations, sick days, life events. </li>
</ul>
</ul>
<br />
<br class="Apple-interchange-newline" />
<hr />
Javascript toolchains by <a href="http://twitter.com/ntschutta">Nathaniel Schutta</a><br />
Here is their take on the JS toolchain<br />
<br />
<ul>
<li>Node.js - Even if not for the server-ness, it is needed for the other essential tools</li>
<li>Grunt - build tool</li>
<li>Jasmine - testing</li>
<li>Mocha -testing with built in async and code coverage</li>
<li>Karma - automatic test execution</li>
<li>Phantom - Headless browser for CI</li>
<li>Sinon - spies, mocks, and stubs</li>
<li>Istanbul - code coverage</li>
<li>JSHint - static code analysis (more configurable then JSLint)</li>
<li>Plato - static code analysis with complexity reports & maintainability indexes</li>
<li>Angular - MVC large application management</li>
<li>Bootstrap - CSS framework</li>
<li>Require - dependency management</li>
<li>Uglify - JS compressor</li>
</ul>
<br />
<div>
<br class="Apple-interchange-newline" />
<hr />
For the rest of the sessions that I attended, while they were interesting, I'm not going to summarize them.<br />
<br />
<ul>
<li>Leading Technical Change, while good to hear again, was all common sense. There was a good quote that came out it though. "Attention is our best resource, don't waste it." "Attention is a bit like real estate, in that they're not making any more of it. Unlike real estate, though, it keeps going up in value" </li>
<li>Web Security was amazingly interesting, especially in the fact that we didn't just go over the obvious vectors, but we actually did the OWASP's web goat security demonstration application as a group lab. That was AWESOME!</li>
<li>Clojure in 10 big ideas was great at getting my head around a purely functional language. It would do no good to summarize or list the 10 points, because without the 15 supporting slides for each point, it is useless. </li>
</ul>
<br />
<hr />
Book Recommendations from the conference</div>
<div>
<br /></div>
<ul>
<li><a href="http://8%26sr%3D8-2%26keywords%3Djava+performance%26tag%3Dkolelepto-20%26camp%3D212677%26creative%3D384117%26linkcode%3Dur1%26adid%3D0en8t40bvqfz0ncs99mq%26/">Java Performance</a> (Specifically Chapters 3,5,7... and a 2nd edition should be coming out soon)</li>
<li><a href="http://www.amazon.com/Functional-JavaScript-Introducing-Programming-Underscore-js/dp/1449360726/ref=sr_1_1?s=books&ie=UTF8&qid=1406173216&sr=1-1&keywords=functional+javascript&tag=kolelepto-20&camp=212677&creative=384117&linkCode=ur1&adid=0EN8T40BVQFZ0NCS99MQ&">Functional Javascript</a></li>
<li><a href="https://www.blogger.com/"></a><span id="goog_519516754"></span><span id="goog_519516755"></span><a href="http://www.amazon.com/Javascript-Allong%C3%A9-Reginald-Braithwaite-ebook/dp/B00FLKRCVO/ref=sr_1_1?s=books&ie=UTF8&qid=1406173272&sr=1-1&keywords=javascript+allonge&tag=kolelepto-20&camp=212677&creative=384117&linkCode=ur1&adid=0EN8T40BVQFZ0NCS99MQ&">Javascript Allonge</a></li>
<li><a href="http://www.amazon.com/gp/product/0156033909/ref=s9_simh_gw_p14_d0_i1?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=1R1AV9712XB7PHHS399H&pf_rd_t=101&pf_rd_p=1688200382&pf_rd_i=507846&tag=kolelepto-20&camp=212677&creative=384117&linkCode=ur1&adid=0EN8T40BVQFZ0NCS99MQ&">Mistakes were made (but not by me)</a></li>
</ul>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com1tag:blogger.com,1999:blog-7392132758872548721.post-52143122064909318342014-06-03T08:51:00.000-07:002014-06-03T08:51:02.005-07:00JPA Annotations and Migrating from SQLServer to Derby in unit tests: A debugging case study <h3>
Problem: </h3>
Our service layer has a series of integration tests that rely heavily on the data in the SQL Server development database. This was fraught with issues.<br />
<br />
<ul>
<li>If the status of a targeted record changed, the tests would fail</li>
<li>If the test had an error, it would fail to cleanup and there would be "unitTestUsers" left in the db. </li>
<li>If you were debugging, and didn't finish test execution, it wouldn't clean up the record</li>
<li>It was slow and required VPN access </li>
</ul>
<br />
<h3>
Solution: </h3>
<div>
Move to Derby, which is an in-memory Java database.<br />
<br />
Obviously we knew that we'd have to create all of the lookup tables, like the us_states table, and the roles table.<br />
<br />
But we ran into numerous bugs which warrant a blog post. I'm going to list them in order and how I solved them, but like an onion, resolving one layer lead to another and another.<br />
<h3>
Background: </h3>
<div>
We are using JPA Annotations in a JAXB framework to manage the persistence. Derby (should) read these annotations and auto-generate the tables.<br />
<br />
<h3>
Roadblock: </h3>
<div>
Missing tables:<br />
<br />
We were getting a dozen missing tables and the tests would have the following errors:<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DatabaseException</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Internal Exception: java.sql.SQLSyntaxErrorException: Table/View 'RC_ACTIVITY_LOG' does not exist.</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Error Code: 20000</span><br />
<br /></div>
</div>
After exploring typos, case sensitivity, persistence.xml settings and configurations, there were two solutions that came out. The short version is that there were 2 errors that were happening during the create table phase.<br />
<h3>
Discoveries: </h3>
<div>
Turning on logging to "Fine" in the persistence.xml will output all of the SQL that is being run.<br />
<span style="font-family: Courier New, Courier, monospace;"><property name="eclipselink.logging.level" value="FINE" /></span><br />
<br />
Then, the log is very, very long (obviously), and was being cleared from the console.<br />
So then I saved the output to a file.<br />
<br />
This is easily done within IntelliJ in the Run/Debug Configurations window. There is a 3rd tab called "Logs" and a checkbox to indicate "Save console output to file:"<br />
<br />
The following errors were discovered:<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Internal Exception: java.sql.SQLSyntaxErrorException: Column name 'IDX' appears more than once in the CREATE TABLE statement. </span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Error Code: 30000</span><br />
<br />
With the corresponding SQL Statement:<br />
<span style="color: yellow; font-family: Courier New, Courier, monospace;">CREATE TABLE job_category (occupation_id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, major_group_id VARCHAR(255), profile_nbr INTEGER, idx INTEGER, idx INTEGER, PRIMARY KEY (occupation_id))</span><br />
<br />
Notice the double "idx INTEGER?"<br />
<br />
After much research, finally found that it was coming from our Annotations:<br />
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@OneToMany(cascade = CascadeType.ALL, mappedBy="profile", orphanRemoval = true)</span><br />
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@OrderColumn(name="idx") </span><br />
<br />
Couldn't figure out why it was doubling, but changing the name="idx" was reflected in the error (still doubled), and leaving it out resulted in the default name doubled. If you have an answer or link to why it doubles, and a better solution, I'd love to hear about it.<br />
<br />
Ultimately, ended up copying the SQL statement from the logs, removed one of the idx references and recreated the table at the beginning of our tests.<br />
<br />
Here is the code for that:<br />
<pre class="brush: java"> private static void createTable(String sql) throws Exception
{
Connection connection = getConnection();
Statement stmt = connection.createStatement();
stmt.executeUpdate(sql);
}
private static Connection getConnection() throws ClassNotFoundException, SQLException {
String strConnectionURL = "jdbc:derby:memory:TestDB;create=true";
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
return DriverManager.getConnection(strConnectionURL);
}
</pre>
<br />
But then we ran into another problem error creating tables:<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Internal Exception: java.sql.SQLSyntaxErrorException: Constraints 'SQL140602131233001' and 'SQL140602131233000' have the same set of columns, which is not allowed. </span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Error Code: 30000</span><br />
<br />
With its corresponding SQL<br />
<span style="color: yellow; font-family: Courier New, Courier, monospace;">CREATE TABLE rc_activity_log (rc_activity_log_id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL UNIQUE, created_on_dt TIMESTAMP NOT NULL, NOTE VARCHAR(255), user_id INTEGER NOT NULL, profile_nbr INTEGER, PRIMARY KEY (rc_activity_log_id))</span><br />
<div>
<br /></div>
<div>
And the Annotations: </div>
<div>
<div>
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@Id</span></div>
<div>
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@GeneratedValue(strategy = GenerationType.IDENTITY)</span></div>
<div>
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@Column(name="rc_activity_log_id", unique=true, nullable=false)</span></div>
</div>
<div>
<br /></div>
Which means that because there is an @ID and unique=true, that it creates two identical constraints on the table, which causes it to fail. (Thanks <a href="https://java.net/jira/browse/GLASSFISH-3252">https://java.net/jira/browse/GLASSFISH-3252</a>)<br />
<br />
Given that the code was working before the derby migration, and we didn't want to change any of that, We just manually created these tables as well.<br />
<br />
<h3>
Extra: </h3>
<div>
One thing that was particularly helpful was being able to determine the actual tables that existed in memory. So from <a href="http://stackoverflow.com/questions/7411020/calling-derby-java-db-show-tables-from-jdbc">http://stackoverflow.com/questions/7411020/calling-derby-java-db-show-tables-from-jdbc</a> we have:<br />
<br />
<pre class="brush: java">
public static void printDerbyTables() {
//http://stackoverflow.com/questions/7411020/calling-derby-java-db-show-tables-from-jdbc
try {
Connection connection = getConnection();
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet resultSet = dbmd.getTables(null, null, null, null);
System.out.println("DERBY TABLES >>>>>>>>> ");
while (resultSet.next()) {
String strTableName = resultSet.getString("TABLE_NAME");
System.out.println("TABLE_NAME is " + strTableName);
}
System.out.println("<<<<<<<<<<<<< END DERBY TABLES ");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
</pre><br />
<br /></div>
<br />
<div>
<br /></div>
<br />
<br />
<br /></div>
<br />
<br /></div>dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-6769123635787473522014-04-16T20:58:00.000-07:002014-04-16T20:58:15.553-07:00Flex debugging timing out in Firefox<span style="font-family: Arial, Helvetica, sans-serif;">Recently I was debugging a project in Firefox and couldn't step through the code for more than a minute before I would get disconnected. </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
Discovered this link</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="https://coderwall.com/p/fhhdla">https://coderwall.com/p/fhhdla</a></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
Which suggests: </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<ol>
<li><span style="font-family: Arial, Helvetica, sans-serif;">In your url bar type in "about:config" without the quotes.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Locate the search field at the top of the document and enter: "dom.ipc.plugins.timeoutSecs" without the quotes.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Double click on that item and set its value to what ever you'd like to increase the amount of time before it considers a plugin hung. 4 NOTE: if you change that value to -1 it should never time out.</span></li>
</ol>
<ol>
</ol>
<ol>
</ol>
<span style="font-family: Arial, Helvetica, sans-serif;">And it seems to work for me, your mileage may vary. </span><br />
<br />
<div>
<span style="font-family: MuseoSans-300, arial, sans-serif;"><br /></span></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-70410460782366159902014-03-10T21:15:00.002-07:002014-03-10T21:25:35.050-07:00Udacity Online Training Review<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><span style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><a href="https://www.udacity.com/course/ud617"><img border="0" src="http://2.bp.blogspot.com/F0cNMUImeVtFT84L76yJk9tdmEBOHbHDYEsEZdsQ_9bVSFqqORbPh3CJO64VOqjeTOihkngA6XQqYN2hDg=s277#w=1757&h=1080" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.udacity.com/course/ud617">Udacity Hadoop and MapReduce</a></td></tr>
</tbody></table>
I recently took the <a href="https://www.udacity.com/course/ud617">Udacity Hadoop and MapReduce</a> online course, with the extra classroom / coaching option. The other interesting aspect was that a number of my coworkers at <a href="http://www.twintechs.com/">Twin Technologies </a> took the class at the same time.<br />
<br />
I come at this course from a unique context. Not only am I a senior developer, but I'm also a university professor, a professional technical trainer, and my wife will have a a PhD in educational psychology in May. (This is relevant in our shared discussions about learning and trends).<br />
<br />
I thought that this course was excellent. I liked that the videos explained the big picture, but there there was hands on, real world exercises to practice with. The multiple choice / multiple answer questions throughout the video were a little annoying, but I recognize the need for assessment if you are going to be offering a certificate at the end.<br />
<br />
I appreciated that the data sets were "messy", some being incomplete or in different formats, and that you had to add error checking to your code. It was great to actually have to get in a do some real examples. I'm happy that the exercises weren't step-by-step, as I have found that most students I've had were pretty good at following directions, but after the exercise is over, they really didn't get anything from the "happy path".<br />
<br />
One of the things that struck me as interesting, was since this class is mostly automated, that there is a "right" answer. This was useful, as it allowed for safe failures and fast feedback, both of which promote leaning. It was also frustrating, when in some of the exercises the answer that I got was not what the computer wanted, mainly because of an anomaly in the data.<br />
<br />
For example, one of the exercises was to determine the most frequently accessed file, and how often had it been accessed. I found the file easily enough, but I was 4 off the total. The course software only told me I was wrong. I had to read through the discussion to determine that I was 4 off, and what the reasons behind it. Apparently, 99.98% of the files were relative paths in the log files that we were processing. But there was that .01% that had absolute paths. This meant that the file in question didn't match the specific string criteria that the others did, and thus ended up outside the total.<br />
<br />
Overall this was a good lesson to learn, that the data might come in forms that are unexpected. However, I feel in the real world, missing that .01% would have been an acceptable oversight. Mostly I was frustrated at the extra time that the exercise required to determine this.<br />
<br />
The coaches were readily available, and certainly had a good handle on coaching.... asking leading questions, listening, providing appropriate feedback without giving away the answers. That was nice to see, and I always enjoyed talking to them.<br />
<br />
The exit interview was a novel idea. Obviously part of the interview is for you to prove you are who you said you are, which I'm assuming is for whatever accreditation Udacity is seeking. But the other interesting part is the feedback. Being an agileist, feedback is hugely important and good feedback is really difficult to come by. So I ended up talking to the interviewer for longer than he probably expected, but I offered up lots of ideas for improvement as well as my thoughts on the course (some of which are reflected here). One thing to note is that scheduling the exit interview is about 1 week away from the time of request. If you are seeking certification and no the subscription plan, you will want to account for that extra time.<br />
<br />
It was fantastic to take this course with some of my co-workers. Of course we all worked at a different pace, but in a remote environment to be able to have a shared experience outside of our annual meetings and project work, is really valuable for team building. It was nice to be able to share our successes and pitfalls. I especially liked having other people checking in with each other to make sure we were all still moving along. I enjoyed feeling like I was helping when I could clarify a question or tell people to read the discussion or notes before starting on an exercise. It certainly was more personal and satisfying than posting to the forum.<br />
<br />
My take away from taking this class, is that while not new information, I certainly prefer to be higher up on <a href="http://en.wikipedia.org/wiki/Bloom's_taxonomy">Bloom's taxonomy of learning</a> with fast feedback, safe failures, and "messy" real world data / problems in my learning opportunities.<br />
<br />
Next time, I would push myself to complete it a little faster so that I didn't incur a 2nd month charge of the subscription fee though.<br />
<br />
<br />dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-87019247833733536892014-01-27T08:25:00.000-08:002014-01-27T08:45:42.749-08:00Using Twitter for classroom queue management<h3>
Problem: </h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCx6IIOpZfFMapqsMiaNSrXW_NzT_CFrLLa-9mCdEOOlN_Z4o_ubBG2ezh2ELJvtHu48nJsJB3B9-Sr9xFQtrOYPWkOJNxuySta0IcU8ridrq1uR-Xz5jeNhMhtaQHwTvkrNesH7cBKkxQ/s1600/stock-footage-line-of-blue-people-human-resources-queue-worker.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCx6IIOpZfFMapqsMiaNSrXW_NzT_CFrLLa-9mCdEOOlN_Z4o_ubBG2ezh2ELJvtHu48nJsJB3B9-Sr9xFQtrOYPWkOJNxuySta0IcU8ridrq1uR-Xz5jeNhMhtaQHwTvkrNesH7cBKkxQ/s1600/stock-footage-line-of-blue-people-human-resources-queue-worker.jpg" height="111" width="200" /></a>I teach a hands-on multimedia class of 25-30 students. During lab times, the students often need help. I was finding that as I was helping one student, their neighbor would grab me as soon as I was done, and I could never get to the other side of the room.<br />
<br />
I wanted a way to create a queue that made it fair to all students.<br />
<br />
<h3>
Constraints:</h3>
<br />
<ul>
<li>Students didn't need an account or access for it</li>
<li>Would always be available, so that if they were having a problem before class, they could be first in line</li>
<li>There was a mobile option, so I could check the queue while walking around the room. I didn't want to have to go back to the computer to determine who was next</li>
<li>I could get a notification if I didn't have the queue running on my machine</li>
<li>Students saw their location in the queue. </li>
<li>It was easy, without many moving parts. This was something that I needed to stand up in a couple of hours and work reasonably well. </li>
</ul>
<h3>
Solution: Twitter as the backend</h3>
<div>
<br /></div>
<div>
Twitter offered everything that I needed. </div>
<div>
<ul>
<li>Already managed and ordered timestamps</li>
<li>Already had access and notifications on my phone</li>
<li>Some students already had accounts, but a dev twitter account and simple custom interface would allow for anybody to access it</li>
<li>Search for the special hashtag, and the queue comes up. </li>
</ul>
<div>
And as an added bonus, I got a chance to play with Node.js, socket.io, JQuery, jade templating, Heroku hosting and a bunch of other technologies which were new to me. </div>
</div>
<div>
<br /></div>
<div>
The end result is that the students LOVE it. They recognize that it is fair, and that it is really easy for them to use at any time. </div>
<div>
<br /></div>
<div>
Inspired by Google, my UI was super simple :<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://content.screencast.com/users/dshefman/folders/Jing/media/1385e3d1-d51a-43df-8ccd-1bd0368fbc09/2014-01-24_1508.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://content.screencast.com/users/dshefman/folders/Jing/media/1385e3d1-d51a-43df-8ccd-1bd0368fbc09/2014-01-24_1508.png" height="65" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The tweet looks like "Drew Shefman needs help #uhmultimediaHelp @UHMultimedia 1390595370659"</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Drew Shefman is obviously the first and last name. </li>
<li>#uhmultimediaHelp is the hashtag that I've choosen. (University of Houston multimedia). This is ultimately my search term. </li>
<li>@UHMultimedia is a DIFFERENT twitter account than the dev account. It is the twitter account I use for my class for announcements. I include this in the message, so that I will receive email notifications. </li>
<li>The number at the end is the timestamp in milliseconds. I found that if a student asked for help twice, that it was not showing up a 2nd time, because twitter prevents a duplicate tweet in a short time period. </li>
</ul>
<br />
<h4>
So here is the flow: </h4>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ol>
<li>On page load and before page display, twitter.search() for #uhmultimediaHelp</li>
<li>Filter out any tweets older than 5 hours (my class is only 3 hours long)</li>
<li>Display results on page, showing name and formatted time (HH:MM)</li>
<li>Student enters name and hits "I need help" </li>
<li>Socket broadcasts new entry and it gets prepended to the list element<br />(this is primarily so that there is immediate feedback, and the impatient students know not to submit multiple times)</li>
<li>twitter.updateStatus()</li>
<li>On twitter submit success, repeat twitter.search()</li>
<li>On search success, socket broadcasts a refresh with the resultant search list.<br />(I perform this seemingly duplicate step of refresh so that if any students are using their personal twitter account, with the hashtag, they will get pulled into the queue. I decided to not use twitter.stream() api as it added a significant layer of complexity. The majority of my students opt for my interface versus using their accounts, so this is a reasonable solution for now. This decision will fail if the number of personal accounts outweighs this queue, as there is only a twitter refresh when a student submits through the queue. </li>
<li> Then, starting from the bottom of the list, I can help the students in order. Woot!</li>
</ol>
<h4>
Technical challenges: </h4>
<br />
<div class="separator" style="clear: both; text-align: left;">
This was my first foray into a decently complex HTML5 / Node app. So starting out *everything* seemed to be a technical challenge. So outside of googling nearly every single line of code I was typing, here are the specific things that I ran into. </div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>I choose <a href="https://github.com/AvianFlu/ntwitter">ntwitter</a> as the node package to leverage for the twitter api. Unfortunately it had not been updated to Twitter's new 1.1 API. So I had to fork it, and modify it for that. You can get that version on <a href="https://github.com/dshefman/ntwitter">https://github.com/dshefman/ntwitter</a>. The change to the 1.1 was simple and you can see it at this <a href="https://github.com/dshefman/ntwitter/commit/134506f63069dbf2b03eb39ad8e18b4314a0a9b9">commit</a>. </li>
<li>I tried using the twitter.stream API, but it requires a single instance. But each connection (webpage) was trying to create a new stream. After much researching, there was an idea to create two Heroku instances, one for the stream and one for the app. This was going to be too much work, so I took a different path.</li>
<li>On Heroku, I pushed up my repository without following the instructions, basically leaving out the init(). Boy it didn't like that. Basically had to delete my whole Heroku account and start over. </li>
<li>My timezone is -5 from GMT, which is what twitter uses. Not a problem, until 7pm (my class is from 5:30 - 8:30pm). At 7pm CDT, that is 12am GMT (00:00:00), in which all of my displayed times switched to -5. It was a simple solution, but something I didn't account for when I was testing it during the day. </li>
<li>Initially I didn't provide fast enough feedback, and the students would submit a half a dozen times before it would show up on their screen. Then they were embarrassed for submitting so much. </li>
</ul>
<br />
<h4>
Technologies Leveraged (Each was decently new to me):</h4>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>CSS </li>
<li>Jade templating </li>
<li>JS</li>
<li>Jasmine BDD</li>
<li>Karma test runner (continuous mode is SUPER cool)</li>
<li>Node.js / Express</li>
<li>Socket.io</li>
<li>Twitter API via ntwitter</li>
<li>Heroku node hosting</li>
<li>JQuery</li>
</ul>
<br />
<h4>
Usage example</h4>
<div>
<br />
<span style="font-family: Arial, Helvetica, sans-serif;"><object id="scPlayer" class="embeddedObject" width="100%" height="346" type="application/x-shockwave-flash" data="http://content.screencast.com/users/dshefman/folders/Jing/media/aed253bb-1667-47b7-b904-9fa65bad9b37/jingswfplayer.swf">
<param name="movie" value="http://content.screencast.com/users/dshefman/folders/Jing/media/aed253bb-1667-47b7-b904-9fa65bad9b37/jingswfplayer.swf">
<param name="quality" value="high">
<param name="bgcolor" value="#FFFFFF">
<param name="flashVars" value="containerwidth=860&containerheight=346&thumb=http://content.screencast.com/users/dshefman/folders/Jing/media/aed253bb-1667-47b7-b904-9fa65bad9b37/FirstFrame.jpg&content=http://content.screencast.com/users/dshefman/folders/Jing/media/aed253bb-1667-47b7-b904-9fa65bad9b37/00000005.swf&blurover=false">
<param name="allowFullScreen" value="true">
<param name="scale" value="showall">
<param name="allowScriptAccess" value="always">
<param name="base" value="http://content.screencast.com/users/dshefman/folders/Jing/media/aed253bb-1667-47b7-b904-9fa65bad9b37/">
</object>
</span>
</div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
</div>
<div>
<h4>
Code:</h4>
You can find the project at:<br />
<a href="https://github.com/dshefman/TwitterHelpQueue">https://github.com/dshefman/TwitterHelpQueue</a><br />
<br />
There is one file missing: twitterAPICredentials.js<br />
You will need to add your own API keys if you want to use the code.<br />
<br />
Since I'm fairly new to all of these technologies, I gladly welcome feedback / best practices for improvement. Thanks! </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com2tag:blogger.com,1999:blog-7392132758872548721.post-69869979476761249152014-01-02T11:08:00.002-08:002014-07-25T21:25:12.992-07:00SCNA 2013 review<br />
<br />
I attended <a href="http://scna.softwarecraftsmanship.org/">Software Craftmanship North America (SCNA)</a>, this past November (2013) and wanted to share some of the major things that I got from this conference.<br />
<br />
Software Craftmanship is a philosophy about developing software and raising the bar of the entire profession. The <a href="http://manifesto.softwarecraftsmanship.org/">craftmanship manifesto</a> augments the <a href="http://agilemanifesto.org/">agile manifesto</a> and adds that the craftsman also values well-crafted software, steadily adding value, community of professionals, and productive partnerships.<br />
<br />
SCNA is the conference for raising the bar. It is a language / technology agnostic conference. It is a community of people who share the above values. The opening remarks of the conference are "Your annual attitude adjustment," which is absolutely true. I find the conference humbling and inspiring and everyone there cares about my growth as a developer. Thank you <a href="http://www.twintechs.com/">Twin Technologies</a> for sending me.<br />
<br />
<hr />
<a href="http://www.nationalrighttolifenews.org/news/wp-content/uploads/2013/11/Healthcaregov73.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://www.nationalrighttolifenews.org/news/wp-content/uploads/2013/11/Healthcaregov73.jpg" height="120" width="200" /></a>The conference started with a reprimand from renown author and personal inspiration <a href="https://twitter.com/unclebobmartin">Robert Martin</a>. His admonition was regarding the heathcare.gov debacle and how it's fallout has and will negatively effect our profession.<br />
<br />
The take away from his presentation was regarding the "responsibility of knowing". Somewhere, some developer knew that heathcare.gov, wasn't tested and ready for production. Relating this to the Challenger explosion, Robert Martin asserts that we, professional software developers, MUST be able to stand firm when we "know" that something isn't ready. A technology problem has now become a policy problem, where technology is preventing a legally created policy from happening. He cited some great references to the <a href="http://c2.com/cgi/wiki?DeveloperBillOfRights">Developer Bill of Rights</a> and <a href="http://c2.com/cgi/wiki?CustomerBillOfRights">Client Bill of Rights</a>.<br />
<br />
<hr />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://malavenda.files.wordpress.com/2012/03/harold-and-the-purple-crayon-ipad-iphone-600x450.jpg?w=300&h=241" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://malavenda.files.wordpress.com/2012/03/harold-and-the-purple-crayon-ipad-iphone-600x450.jpg?w=300&h=241" height="160" width="200" /></a></div>
<a href="https://twitter.com/fablednet">Sara Gray</a>, then presented a fantastic analogy regarding writing new worlds. Her statement is that you create the [programming] world that you live in, and are you thinking about the others (including your future self) that will have to live in that world. The analogy that she used was Harold and the Purple Crayon. You get to create your world and everything that you need, but sometimes you accidentally create monsters.<br />
<br />
Sara asserts that like parts of a sentence, that there are parts of code. There are named things, like variable, parameters, and methods. There are pieces of knowledge, which should be extracted and then named. There are changes of state, which could be represented as "who changes state", and might be a good place for helper classes. Finally, there is the "speaking voice", which I believe is the overall flow.<br />
<br />
<hr />
<a href="http://programmedevelopment.com/public/uploads/images/team_raise_graph_pa_500_clr.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://programmedevelopment.com/public/uploads/images/team_raise_graph_pa_500_clr.gif" height="200" width="165" /></a><a href="https://twitter.com/kauerrolemodel">Ken Auer</a> says that you can't live on stackoverflow or github alone. The goal is to raise the bar, not win an arguments. When addressing poor code, the goal should be to raise the bar, to transfer knowledge in a constructive way, and not win the argument by proving your superior knowledge. He gave his mantra, which was "make it run, make it right, make it fast", but recognize that "make it right" is limited by the most skilled participant. Based on the Dreyfus learning models, the novice has to be "in sight" of the expert, in order for them to grow. One of the nuggets that I always look for at conferences is potential interview questions. Ken provided a good one. "What software have you shipped?"<br />
<br />
<br />
<hr />
One of the most thought provoking, and immediately applicable sessions was given by <a href="https://twitter.com/cczona">Corina Zona</a>, entitled "Schemas for the Real World". Her assertion is that giving a form field a name or restricted answers limits its scope, and that you could declare a person invalid. People are never edge cases. Some examples would be a gender field of male/female; a sexuality field of hetero/bi/gay; drop down boxes for religion, race, or relationship status. The user often has to choose to be inauthentic to fill in these fields, saying "this isn't really me, but it is the only option". Why can't all of these fields be text inputs? What questions are we really trying to answer? Maybe the question that you are trying to answer, instead of asking for gender, ask "what pronoun do you prefer?" Based on her research, when given a free text option for gender, only 40% responded with "m, f, male, or female".<br />
<br />
<a href="http://itspronouncedmetrosexual.com/wp-content/uploads/2012/06/somebody-gets-me-comic.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://itspronouncedmetrosexual.com/wp-content/uploads/2012/06/somebody-gets-me-comic.jpg" height="204" width="320" /></a><br />
Here is another example of potential invalidation: Facebook's relationship status. Does it alienate people not in or not looking for a relationship? When does a "widowed" status change to "single"? How is the "Married, Separated, and Looking" status represented?<br />
<br />
The cool thing about this session, was that that evening I had dinner with some college friends who work in admissions in higher education. We discussed that this was the exact thing that they <b>*battle*</b> with their IT group all of the time. It is very unusual to have a long lasting conversation about the things that I've learned in a conference with non-developers.<br />
<br />
The other neat aspect of this, was that I was able to put it to use in the next form that I created. I'm organizing a parent / child dance for my daughter's school, and on the form, instead of having check boxes for mother and father, I have the following field: "Relationship of the attending adults to the child(ren)." This will hopefully give me the answers that I'm looking for... answers like "mother and father, step-father, mom1 and mom2, grandmother, etc". It provides a very rich data set.<br />
<br />
<hr />
<br />
<a href="http://www.referenceforbusiness.com/photos/total-quality-management-tqm-504.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://www.referenceforbusiness.com/photos/total-quality-management-tqm-504.jpg" height="200" width="200" /></a>The panel on software quality had some interesting insights. Does quality even exist? Given that it, quality, is an individual definition, it might not even be describable until you can see it or see its absence. Interestingly enough, is that quality has no value today. It has value tomorrow; it is something that you pay forward. Simplicity, which is often the sign of good quality, takes experience because it is hard. Testing is a good *tool* that might be an indicator of quality, but it is not a rule that tests mean high quality.<br />
<br />
<br />
<br />
<br />
<hr />
<a href="https://twitter.com/pragdave">Dave Thomas</a>, one of the Pragmatic Programmers,<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://tgconnection.org/wp-content/uploads/2012/02/survey-question-mark.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://tgconnection.org/wp-content/uploads/2012/02/survey-question-mark.jpg" height="200" width="200" /></a></div>
talked about the unknown knowns and that we should teach people what we were taught, but infuse them with what we have learned. Given the matrix of what you know that you know, what you know that you don't know, what you don't know you don't know, and the what you don't know that you know; it is this last one, the unknown knowns that might be the most valuable. It is the cumulative integration of your experiences, and the critical piece which we have to try to share. A simple example to references is how do you recognize a face, or describe how you walk. Thinking about them actually breaks your ability to use the knowledge. The parts that we need to transfer, is why did you structure the code this way instead of that, or why does this code make you feel dirty?<br />
<div>
<br />
<hr />
<a href="https://twitter.com/sandromancuso">Sandro Mancusio</a> provided some insight into some of the criticism and rebuttal that the craftmanship movement has encountered. </div>
<div>
<br /></div>
<div>
The first criticism is the "craftmanship is just XP rebranded". Craftmanship is an ideology not a methodology like XP. It is about principles not practices. Practices are chosen based on the value that they bring. </div>
<div>
<br /></div>
<div>
"Craftmanship is an elitist movement." Actually, we (the crafts-people) are fully inclusive, trying to raise the bar across the industry. We recognize and support the need of novices. We NEED them for everyone to grow. </div>
<div>
<br /></div>
<div>
"First crafted code, then whatever the client wants." We practice writing quality code, so that time is not a factor to deliver quality. Quality becomes inherit in our work. </div>
<div>
<br /></div>
<div>
"Pragmatism over religion." The message is professionalism, it is not TDD or practices. "What does it mean to be a craftsman", is not universally definable, but a personal definition. How it is done is as important as having it done. </div>
<div>
<br /></div>
<div>
One thing that struck me as particularly powerful, was his mentor's description of his first attempt at code as "disrespectful". Out of all of the adjectives available to him.... "bad, inefficient, ugly, unmaintainable", he choose disrespectful. That is quite an interesting context. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<hr />
<br /></div>
<div>
<a href="http://www.quality-improvement-matters.com/images/team-solving-puzzle2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://www.quality-improvement-matters.com/images/team-solving-puzzle2.jpg" height="143" width="200" /></a>On the nature of software development, by <a href="https://twitter.com/RonJeffries">Ron Jefferies</a> and <a href="https://twitter.com/chethendrickson">Chet Hendrickson</a>, they assert that most agile teams have it wrong. Coding is a team sport, and that everyone on the team should be somewhat capable of "scoring" even if that isn't their primary duty. Backlog refinement shouldn't be the sole job of the product owner, but a team problem-solving effort. The whole team needs the vision of the product, the "what are we building". The team is actually the product owner, and the product owner is technically the "product champion" </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<hr />
Finally outside of what I've already written about, there were some notable quotes that I wanted to share. </div>
<div>
<ul>
<li>Trust-driven development. How transparent can you be to build trust? </li>
<li>"Does my commit increase or decrease the entropy of the system?"</li>
</ul>
<div>
<br /></div>
</div>
<div>
Oh and one last thing. I was able to participate in a code retreat at 8th Light. I'm very envious of their bookshelf.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiiImCEO5K-7VKRPBwL1Yvbb7htKQyR8WThPqxPIwdpbTu6wXG9NgumeQ9pX0HHTRRpZicPt45yWmWTUiPOZ4RDXWotUBt4fJ_spSyqwjjwFTVXYSl6svvqR0bHlmm4QME3-Jd4xaxJZ0H/s1600/20131110_091137.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiiImCEO5K-7VKRPBwL1Yvbb7htKQyR8WThPqxPIwdpbTu6wXG9NgumeQ9pX0HHTRRpZicPt45yWmWTUiPOZ4RDXWotUBt4fJ_spSyqwjjwFTVXYSl6svvqR0bHlmm4QME3-Jd4xaxJZ0H/s640/20131110_091137.jpg" height="480" width="640" /></a></div>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-42415224870491175402013-12-30T13:53:00.000-08:002013-12-31T13:44:18.714-08:00Sequence Based FlexUnit integration testingDid you know that sequence based testing is built into FlexUnit? I was relieved to find this link in the documentation (<a href="http://tutorials.digitalprimates.net/flexunit/Unit-13.html">http://tutorials.digitalprimates.net/flexunit/Unit-13.html</a>). If you go to that page, please scroll to the bottom section about "Using Sequences".<br />
<div>
<br /></div>
<div>
One of <a href="http://twintechs.com/">Twin's</a> clients needed a real time update for currency exchange. Basically in our system, instead of a continuous feed, the business requirement was that every week the admin would enter the new exchange rates (there were only 5 that were relevant). Once saved, there was supposed to be a real time push notification to all open clients so that they could update their forecast data. </div>
<div>
<br /></div>
<div>
Here is what my integration test needed to prove: </div>
<div>
<ul>
<li>Get the current exchange rates from the service</li>
<li>Save a new exchange rate</li>
<li>Receive the push notification</li>
<li>Validate that the new rates has been recorded into model under the correct date.</li>
</ul>
<div>
<pre class="brush:as3">var rtmpManager:ExchangeRateRTMPManager = new ExchangeRateRTMPManager();
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceCaller(eventDispatcher, getInitialExchanges, [weeks] ))
sequence.addStep(new SequenceWaiter(eventDispatcher, INITIAL_RATES_EVENT,TIMEOUT, handleTimeout));
sequence.addStep(new SequenceCaller(eventDispatcher, saveCurrency ,[er]))
sequence.addStep(new SequenceWaiter(eventDispatcher, SAVE_CURRENCY_EVENT,TIMEOUT, handleTimeout));
sequence.addStep(new SequenceDelay(15*1000)) //Delay 15 s to see if we can get a notification in that time
sequence.addAssertHandler( validateRTMPManagerReceivedPushNotifcation, null);
sequence.run();
</pre>
<br />
Tests passed, and it worked beautifully!</div>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-52401638157299314022013-12-30T13:18:00.000-08:002013-12-31T13:45:33.343-08:00Permissions Modelling in FlexPermissions is something that most of my projects have needed. I've been iterating on a design for many projects, and I've finally come up with something (leveraging some work that my <a href="http://twintechs.com/">Twin teammates</a> have produced) that is scalable, testable, and easy for my team to implement. I've written this up in the context of Flex / Actionscript, but there is no reason why it couldn't apply to other languages.<br />
<div>
<br /></div>
<div>
Just to clarify my requirements, here are the user stories that I'm working with. </div>
<div>
<ul>
<li>Should be testable.<br />As the developer, I want to be able to declare which permissions are present during testing and development independent of my actual permissions on the system. (In other words - decoupled) </li>
<li>Should be scalable<br />As a client, I want to be able to add/remove permissions at any time without major work/rework in the application</li>
<li>Easy to understand<br />As a new or jr. developer, I want to be able to understand and implement permissions in a best practices way</li>
</ul>
<div>
<br />
What I came up with, was a hierarchical string based system. It looks like the following:</div>
<div>
<pre class="brush:as3">public class PermissionTaskConstants
{
public static const DEVELOPER:String = "developer"
public static const ADMIN:String = "admin";
public static const ADMIN_USER:String = "admin.user";
public static const ADMIN_CURRENCY:String = "admin.currency"
public static const LOGIN:String = "login"
public static const PROJECT:String = "project"
public static const PROJECT_EDIT:String = "project.edit"
public static const STAFFING:String = "staffing";
public static const STAFFING_EDIT:String = "staffing.edit";
public static const STAFFING_ALLOCATE:String = "staffing.edit.allocate"
}
</pre>
<br />
In this way, if you were assigned a permission of "staffing.edit.allocate", you would inherit all of the rights of "staffing" and "staffing.edit". This satisfy's the scalable requirement. It is trivial to add or remove permissions, as it would only mean adding / removing strings from the permission path.<br />
<br />
These permissions would live in a "permission registry", which would contain an array of strings. This registry could be populated from a service call to a database, or it could be filled at run time. Filling it at run-time would satisfy the "should be testable" requirement. The code is availabe at the bottom, but I've set it up so that it dispatches events when permissions are changed. A developer can listen for those events and update the UI. Although the typical workflow is that after login, we retrieve the permissions from the database, and the registry is populated before any of the UI is displayed.<br />
<br />
<h3>
<span style="color: yellow; font-size: x-large;">IMPORTANT: Decouple the registry from the view!</span></h3>
So this is super important. In order to make this testable and decoupled, never, ever, ever reference the registry in the view. Said differently MXML files should have NO KNOWLEDGE of the PermissionsRegistry.<br />
<br />
Here is the recommended workflow. You have a MXML file that represents the view. Just for clarification, this view is in charge of the layout and interactions with the user. There should be no business logic in the view.<br />
<br />
Then you have an presentation model (PM) that is in charge of all business logic. This is likely a pure actionscript file. Business logic means conditionals, domain level events, and in this case permissions. The PM receives a copy of the permission registry through dependency injection. The PM then exposes the specific permissions that the view needs through methods.<br />
<br />
The view creates its own Bindable public properties that represent the various permission states, and then reads them from the PM. (Please forgive the incorrect capitalization in the MXML objects, the css "brush" for this formatting strips that out)<br />
<br />
<br />
<pre class="brush:plain"><s:application creationcomplete="creationCompleteHandler(event)" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
<fx:script><![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
public var pm:PermissionsPM;
[Bindable] public var canReadProjects:Boolean;
[Bindable] public var canEditProjects:Boolean;
[Bindable] public var canReadStaffing:Boolean;
[Bindable] public var canEditStaffing:Boolean;
private function creationCompleteHandler(event:FlexEvent):void
{
pm = new PermissionsPM();
canReadProjects = pm.canSeeProjects();
canEditProjects = pm.canEditProjects();
canReadStaffing = pm.canSeeStaffing();
canEditStaffing = pm.canEditStaffing();
}
]]></fx:script>
<s:layout><s:verticallayout></s:verticallayout></s:layout>
<s:button enabled="{canEditProjects}" label="Projects" visible="{canReadProjects}">
<s:button enabled="{canEditStaffing}" label="Staffing" visible="{canReadStaffing}">
</s:button></s:button></s:application>
</pre>
<pre class="brush:as3">package
{
import com.squaredi.permissions.PermissionTaskConstants;
import com.squaredi.permissions.PermissionsRegistry;
import mx.collections.ArrayCollection;
public class PermissionsPM
{
[Inject] public var permissionsRegistry: PermissionsRegistry;
public function PermissionsPM()
{
permissionsRegistry = new PermissionsRegistry();
var permissions:Array = [PermissionTaskConstants.PROJECT_EDIT, PermissionTaskConstants.STAFFING]
permissionsRegistry.permissionsList = new ArrayCollection(permissions);
}
public function canSeeProjects():Boolean
{
return permissionsRegistry.hasPermission(PermissionTaskConstants.PROJECT);
}
public function canEditProjects():Boolean
{
return permissionsRegistry.hasPermission(PermissionTaskConstants.PROJECT_EDIT);
}
public function canSeeStaffing():Boolean
{
return permissionsRegistry.hasPermission(PermissionTaskConstants.STAFFING);
}
public function canEditStaffing():Boolean
{
return permissionsRegistry.hasPermission(PermissionTaskConstants.STAFFING_EDIT);
}
}
}
</pre>
<br />
<br />
A couple of other special features about the code. As a developer I can manually add and remove permissions from the list. When I do this, it sets a "developerUpdated" flag, which will ignore setting the whole array. Here is the use case for that. I login to the system but the service call to get permissions is delayed (for some reason). Then I want to verify how the system looks for other users, and add specific permissions, then the service call comes back and could potentially overwrite the values that I've modified. So there is code in place to prevent that.<br />
<pre class="brush:as3">public function set permissionSource(v:Array):void
{
if (developerUpdated) { return} //Don't allow it to be overwritten if the developer has already set individual permissions for testing
permissionsList.source = v;
permObj = createPermObj(_permissionsList)
notifyUpdate();
}
public function addPermission(permission:String):void
{
var idx:int = permissionsList.getItemIndex(permission);
if (idx <0)
{
permissionsList.addItem(permission);
permObj = createPermObj(permissionsList)
developerUpdated = true;
notifyUpdate();
}
}</pre>
<br />
The other feature that is in the code, is an interface for extracting the data. This could be used in the case of a value object (VO) that returns from the database that has a list of permissions for a given user. This VO is an object, and doesn't have the necessary string representation for permissions. The permission registry accepts an PermissionExtractor helper, that can convert the VO into permissions strings.<br />
<pre class="brush:as3">package com.squaredi.permissions
{
public interface IPermissionExtrator
{
function getPermissionString(perm:Object):String; // returns a.b.c
}
}
</pre>
<br />
All of the code and an example can be found at: <a href="https://github.com/dshefman/FlexPermissions">https://github.com/dshefman/FlexPermissions</a></div>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com2tag:blogger.com,1999:blog-7392132758872548721.post-50112385500843296472013-12-30T09:36:00.000-08:002013-12-31T13:39:35.339-08:00Quick and Free, Remote-Team Planning PokerRecently I was on a hybrid team, made up of representatives from <a href="http://twintechs.com/">Twin Technologies</a> and 2 other companies. We were all over the country, and we needed a way to play planning poker effectively. Given the other tools that we were using, adding an additional tool, credentials, IT clearance, etc. wasn't feasible.<br />
<br />
So we found this great blog post from <a href="http://fourkitchens.com/blog/2012/07/16/scrum-playing-planning-poker-scattered-team">fourkitchens</a> about using a Google Spreadsheet for planning poker.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://squaredi.com/blogswfs/planningPoker/GoogleSpreadsheet.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" height="273" src="http://squaredi.com/blogswfs/planningPoker/GoogleSpreadsheet.png" width="640" /></span></a></div>
<br />
To play planning poker, we all call into the phone / voip conference number and open the google doc. After we discuss each story, everyone enters their story point vote, but doesn't press Enter right away. The scrum master can see that everyone has entered a value when their respective box is highlighted grey. Once everyone has made a choice, the scrum master calls “3, 2, 1: Go” and everyone hits Enter. All values appear on everyone’s screen and the planning poker game continues as normal.<br />
<br />
We color coded the cells based on conditional formatting (Format -> conditional formatting). Each Fibonacci number got its own color. Invalid numbers remained white. This gave an easy visual representation on the distribution of values. <br />
<br />
Now you might have noticed the "Average" line in the photo. We were spending too much time discussing and coming to a unanimous agreement on these estimates. Based on recent recommendations in the Agile world, everyone doesn't have to agree on a number. The numbers do have to be within a spread of 3 though. For example, 2,3,5 or 3,5,8 are valid spreads. The spread has to be there present though: 2,5,5 or 3,3,8 are not valid spreads and would need to be discussed. (The photo above would represent a invalid spread and we'd have to have more discussion until we could bring that in). <br />
<br />
With the adopted averaging the numbers, we would round up to get our estimated point value. Usually what would happen, is that as the team size would unfortunately fluctuate and /or different people could or couldn't attend the planning, we would change what was being averaged. The picture above shows the average only from Rick, Drew, and Larry, and the resulting estimate would be 2 story points (rounding up, or Math.ceil(1.333) :) ) . <br />
<br />
Given this system of averaging, it is likely and common to end up with non-Fibonacci totals for our estimates. That is okay. Since the estimates have no time based correlation, they are only used to determine our velocity and therefore our commitment, using Fibonacci only numbers as the inputs and the average as the output works out really well. Fours, sixes, and sevens in out estimate gave us good insight into velocity. <br />
<br />
Now just to repeat how agile estimates are supposed to work. The estimate is RELATIVELY sized based on team decided criteria. These UNIT-LESS numbers are used solely to determine velocity. It will likely take 2-3 sprints to even figure out what the velocity is. The estimate HAS NO CORRELATION to time. Once the velocity has been determined, then it is used to make the COMMITMENT. The team says, that we can do (x) story points per sprint, so we will commit and GUARANTEE that (x) will be done by the end of the sprint. That is why averaging works in this case, because the numbers roll into the commitment, and not into any time units. <br />
<br />
This system is fast and simple. Adding or removing team members is a no-brainer. Estimating was no longer a chore, nor took up very much time. We could get in and out very quickly and get back to work. I hope that it works as well for you. dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-29735968941812000922013-12-06T07:19:00.000-08:002013-12-06T07:19:12.897-08:00Remoting Landmine without a stack trace or debug ability<b><span style="font-size: large;">Summary:</span> </b><br />
<div>
<br /></div>
<div>
While using AMF remoting, if you get the following error: </div>
<div>
<br /></div>
<div>
<pre>TypeError: Error #1034: Type Coercion failed: cannot convert Object@1456c7b9 to mx.messaging.messages.IMessage</pre>
<br /></div>
<div>
And you've overridden the hashcode to your java VO objects, you will end up in an un-debuggable situation. </div>
<div>
<br /></div>
<div>
<span style="font-size: large;"><b>Solution:</b></span> Remove the hashcode override. </div>
<div>
<br /></div>
<h4>
BackStory:</h4>
<div>
We are migrating database schemas, so I had set up unit tests to compare the results from one schema to the other. I am using JUnit and assertEquals. </div>
<div>
According to the documentation, I should override the equals() method on each object, as that is what the assertEquals uses for the comparison. This was tedious, but then I discovered that Eclipse had a generate equals() and hashcode() methods. Eclipse comments say to always include hashcode when overriding equals. Ok. I confirmed that on google, all things checked out. </div>
<div>
<br /></div>
<div>
What happened though, is that serializing from Java to Flex went fine, but on the return trip --- BOOM. </div>
<div>
The error was an UncaughtErrorEvent.UNCAUGHT_ERROR. The request made it out, according to Charles webproxy, but never actually made it to the endpoint on the other side (Based on the debugging breakpoint). Since it never made it to the service, the normal fault responder didn't fire. Fortunately, I'm trapping all uncaught error messages in Flex. There was no stack trace in Flex or in Java. Just this error thrown from somewhere.<br />
<br />
The only information I could gather from Charles was that it was a StackOverflowError. </div>
<div>
<br /></div>
<div>
I only discovered this information by rolling back one commit at a time, then cherry-picking one file at a time, then one method at a time. Painful! </div>
<div>
<br /></div>
<div>
If you run into this, I hope that I've included enough keywords that you find it quickly and don't waste a whole day like I did. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-24934463417222706622013-08-06T12:55:00.000-07:002015-06-08T19:37:34.697-07:00Software Estimating Tips / Tricks / TrapsThis post is broken down into the following areas<br />
<ol>
<li>The presentation given at<br />
<a href="http://www.360stack.com/">360Stack</a> on Aug 6, 2013<br />
<a href="http://www.houstontechfest.org/SitePages/Home.aspx">Houston TechFest</a> on Sept 28, 2013<br />
<a href="http://scna.softwarecraftsmanship.org/">Software Craftmanship North American</a> on Nov 9, 2013<br /> <a href="http://aplnhouston.org/">Agile Leadership Network</a> - Houston on Feb 20, 2014<br /> <a href="http://pmihouston.org/content.php?page=Annual_Conference">PMIHouston</a> - June 8, 2015</li>
<li>The highlights from the presentation, in case you don't want to read the slides</li>
<li>Resources</li>
<li>Questions that were asked during the presentation</li>
<li>Backstory to the presentation</li>
<li>Cross-links</li>
<li>Feedback and comments</li>
</ol>
<h3>
<br />Software Estimating: Tips for upping your SWAG</h3>
<div>
Here is my presentation<br />
<ul>
<li><a href="http://www.squaredi.com/blogswfs/Estimating/index.html" target="_blank">Software Estimating Presentation (click through version)</a></li>
<li><a href="http://www.squaredi.com/blogswfs/Estimating/Estimating.pdf" target="_blank">Software Estimating Presentation (PDF)</a> - 50 min version</li>
<li><a href="http://squaredi.com/presentations/Estimating7PMI_HOU.pdf">Software Estimating Presentation (PDF) </a>- 75 min version</li>
<li><a href="http://www.squaredi.com/blogswfs/Estimating/Estimating6LightningTalk.pdf">Software Estimating: Lightning Talk (PDF)</a></li>
</ul>
</div>
<div>
<h3>
</h3>
<div>
I'd love to hear your <a href="http://www.surveymonkey.com/s/X6N5CKK">feedback</a>. </div>
<br />
<h3>
9 Tips for improving your software estimating abilities</h3>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.twintechs.com/"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjayKTuf7SCTtL2V9SjRY3y4ohg-26g06td19nzTrdGYeRko5_5n-B3Ke19Iyzx35xcc96c_zUvbRFzGdj3kALRZ1w0gMjupzY55oJx1o2Q58jeKBjZPVE66I-IQyqNnG7Lfz2FXXGGWWs/s640/Estimating+Tip+Summar.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<ol>
<li>Determine if you are supposed to be estimating or hitting a target</li>
<li>Use units that are consistent with the estimates underlying accuracy</li>
<li>Explicitly express the uncertainty in your estimates</li>
<li>Collect and use historical data</li>
<li>Count when possible; compute when you can't count</li>
<li>Do a pre-mortem</li>
<li>Envision someone else (not you) doing the work</li>
<li>Remember the most commonly forgotten project related tasks</li>
<li>NEVER TRY. Do or do not. Manage your commitment and your <a href="http://papers.ssrn.com/sol3/papers.cfm?abstract_id=920625">implied commitment</a> with vigilance. </li>
</ol>
<h3>
</h3>
<div>
<br /></div>
<h3>
Resources:</h3>
<div>
<ul>
<li><a href="http://www.amazon.com/Software-Estimation-Demystifying-Practices-Microsoft/dp/B00B9ZD20K/ref=sr_1_3?s=books&ie=UTF8&qid=1374008469&sr=1-3&keywords=software+estimation">Software Estimation: Demystifying the Black Art</a> by Steve McConnell</li>
<li><a href="http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073/ref=sr_1_1?s=books&ie=UTF8&qid=1374008540&sr=1-1&keywords=clean+coder">Clean Coder</a> by Robert Martin</li>
<li><a href="http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555/ref=sr_1_1?s=books&ie=UTF8&qid=1374008659&sr=1-1&keywords=thinking+fast+and+slow">Thinking Fast and Slow</a> by Daniel Kahneman</li>
</ul>
</div>
<div>
<ul>
<li><a href="http://psygrammer.com/2011/03/12/misunderestimations-part-1/">http://psygrammer.com/2011/03/12/misunderestimations-part-1/</a></li>
<li><a href="http://psygrammer.com/2011/03/16/biases-create-misunderestimations-part-2/">http://psygrammer.com/2011/03/16/biases-create-misunderestimations-part-2/</a></li>
</ul>
</div>
<h3>
</h3>
<div>
<br /></div>
<h3>
Questions from presentation</h3>
</div>
<div>
<ul>
<li>Could you talk about larger projects, like bigger than six months. Do these techniques still apply?<br /> <span style="color: #e69138;">The "Demystifying the Black Art" book is absolutely structured to discuss which techniques work at which stage of the project. It also categorizes by project size, what stage in the project, and type of project (iterative or sequential).</span></li>
<li>How do you build in scope creep into your estimate?<br /><span style="color: #e69138;">Put that into your explicit range as a +2 months for 20% new features, or if you are unsure about the client have a +6 month or whatever risk quantification. </span></li>
<li>Do I charge for estimates?<br /><span style="color: #e69138;">I wish clients would pay for it because it is a lot of work, but sadly, no I don't. </span></li>
<li>Estimating based on historical data... isn't that like your stock prospectus "Past performance doesn't guarantee future performance"?<br /><span style="color: #e69138;">Not really, the market is driven by so many factors, but this isn't the case, this is YOUR historical data. Unless your team has had a complete overhaul of people, or you have done a Matrix like download of new skills, your team's historical data is an incredible accurate model to base similar projects against. But beware of the intuitive trap, use concrete numbers (size, number of stories, number of screens, etc) to do the comparison. If you are using intuition or memory for the comparison, you will likely not get a good estimate. </span></li>
<li>How much effort do I put explaining this [the concepts in this presentation] to the client?<br /><span style="color: #e69138;">I make sure it comes out in my language. First I clarify if I'm creating an estimate or hitting a target. If I'm creating an estimate, I make sure that I use estimate and commitment in the same time frame. Something like the estimate is 5 months, but I can commit to you that I'll deliver something of value, that is less than the whole thing, to you in three months. Give me 2 weeks to get into it, and I can give you a good sense of what that might be. </span><br /><br /><span style="color: #e69138;">The overall trap, is that you want to avoid committing at the big end of the cone, when it is most uncertain and unclear about what the project is about. </span></li>
<li>Do you give one estimate to the employees, and an later estimate to the client, so that way the employees finish early?<span style="color: #e69138;"><br />Personally, this question made me uncomfortable. My answer is no, I see no reason to withhold information or give misinformation to my team. As an Agilist, my client is involved all the time. I show them something every week. There is no question to anybody, either on the team or the client, the exact status of the project and if we are on target or not. When my team makes a commitment, we treat that as such. I can ask my team "I have your word that we will complete all of the things that we say by the time that we said". If your team is not at a place to give their word, to make that commitment, then it is up to you to determine how you would manage your team and client interactions.</span></li>
<li>Tangent : The research and the book "<a href="http://www.amazon.com/Drive-Surprising-Truth-About-Motivates/dp/1594484805/ref=sr_1_1?ie=UTF8&qid=1375855327&sr=8-1&keywords=Drive">Drive</a>" by Daniel Pink was mentioned (and I highly recommend it)</li>
<li>If estimates are non-negotiable, what happens when you get a new piece of information?<br /><span style="color: #e69138;">If you get new information that improves the clarity of the project, and moves you farther into the cone, then by all means, re-estimate. Remember you *should* be re-estimating several times before the end of a project. Estimates are not fixed. </span></li>
</ul>
<h3>
</h3>
<div>
<br /></div>
<h3>
Backstory on this presentation</h3>
</div>
<div>
I had a great time presenting last year at 360Flex, and I wanted to present again. I knew that since the feel of the conference was changing to be less Flex centric, I wanted to make sure to choose a topic that was generic enough. At the time, I was working on this crazy estimate with 100+ highly detailed requirements. </div>
<div>
<br /></div>
<div>
While I was doing this estimate, I thought "I really have no basis for what I'm putting down here.... I'd like to know how to make better estimates" </div>
<div>
<br /></div>
<div>
Also at the time, I was reading several psychology related books, and the overwhelming consistent information coming from these books, that unless you are an expert at a given task (10K applied hours) that your intuition can easily lead you astray. I was certainly not an expert at estimating and I was completely guessing at what the effort was. </div>
<div>
<br /></div>
<div>
Therefore, I declared that "Estimating" was going to be my topic, and threw my hat into the ring, so to speak. Immediately I started researching the topic, just in case I got picked. </div>
<div>
<br /></div>
<div>
The field of estimating is WAAAAAAAY overwhelming. PhD disserations, $100K dollar software packages, complex statistical math, and simple tricks were un-navigably abundant in my initial research. I decided to narrow my talk to the psychology of estimating; simple things that can to to trick your brain to get you to better estimates. </div>
<div>
<br /></div>
<div>
I was reading "Thinking Fast and Slow" at the time, and it seemed to fit perfectly with this decision. Half of this mighty book was about professional forecasters and how our environment influences our estimates. It seemed like the perfect match for this presentation.<br />
<br />
I started out with an outline based on that book, then I was going to fill it in with details from "Demystifying the Black Art". Once I started reading "Demystifying", that was it... the book was perfectly suited to my presentation. The new outline literally flowed out in an half hour sitting.<br />
<br />
It was also fortuitous, because as I was talking to people about the cognitive biases associated with estimating, I got frequent warnings about informing people how poorly their brain works. With these warnings, I was pretty sure that presenting about cognitive biases, it would likely be at best, completely ignored, and at worst, a pretty sizable flame war.<br />
<br />
So after several practice presentations to my wife, my mom, <a href="https://www.linkedin.com/profile/view?id=6360224&locale=en_US&trk=tyah">the most experienced estimator on the Twin Technologies team</a>, and finally all of the <a href="https://www.linkedin.com/company/124331?trk=tyah">Twin Technologies team</a>, I have the presentation that is presented to you at <a href="http://www.360stack.com/">360Stack</a>.<br />
<br />
<br />
<hr />
<br />
One nice discovery that came about this from this presentation is the "How good of an estimator are you" slide, with the 10 questions. When I was in college, my professor gave us these 10 questions as a quiz. He counted the score as part of the grade, which I wasn't pleased with, as I was average for this test, which was 30%. It was comforting to discover that 30% is average, even if he didn't mention that fact, and even 20 years later.<br />
<br /></div>
<hr />
<h3>
Cross links to this blog / presentation</h3>
<div>
<ul>
<li><a href="http://www.twintechs.com/2013/07/sharing-our-software-estimation-expertise-with-the-tech-community/">http://www.twintechs.com/2013/07/sharing-our-software-estimation-expertise-with-the-tech-community/</a></li>
<li><a href="http://aplnhouston.org/index.php/chapter-meetings/upcoming-meetings/299-february-chapter-meeting-february-20-2014">http://aplnhouston.org/index.php/chapter-meetings/upcoming-meetings/299-february-chapter-meeting-february-20-2014</a></li>
</ul>
</div>
<div>
<h3>
Feedback and comments</h3>
<ul>
<li>Fantastic volume of content crammed into a 50 minutes session."</li>
<li>Very practical advice on how to estimate projects. One of my favorite sessions."</li>
<li>best preso ever!"</li>
<li>All around really great! Slides, topic, presentation, speed, q&a, all good</li>
<li>The content was well thought out! You did the #1 rule in presenting (tell 'em, tell 'em, tell 'em).</li>
<li>Getting access to the slides, opening my eyes to the importance of spending extra time on estimates</li>
</ul>
</div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-82998587767359487922013-03-14T20:18:00.000-07:002013-03-14T20:18:11.643-07:00Column Spanning with Flex Spark DataGrid - Part 2I wrote a prior post ( <a href="http://squaredi.blogspot.com/2012/07/column-spanning-with-flex-spark.html" target="_blank">http://squaredi.blogspot.com/2012/07/column-spanning-with-flex-spark.html</a> ) when I was creating a prototype about column spanning.<br />
<br />
I'm going to leave most of the details in that post. I have however put the column spanning into production and discovered some missing logic.<br />
<br />
We had a service, that computed user's allocation per week for 2 months that took a long time to run, and we wanted to not lock up the UI while it was running. We wanted a lazy loading solution, that "blocked" out the cells that were not available yet.<br />
<br />
Here is what that looked like:<br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif;"><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" height="250" id="ColumnSpanning" width="100%">
<param name="movie" value="http://www.squaredi.com/blogswfs/spannableColumns/ColumnSpanningLoadingExampleApp.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="http://www.squaredi.com/blogswfs/spannableColumns/ColumnSpanningLoadingExampleApp.swf" width="100%" height="250">
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--<![endif]-->
<!--[if gte IE 6]>-->
<p>
Either scripts and active content are not permitted to run or Adobe Flash Player version
11.1.0 or greater is not installed.
</p>
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</span><br />
You can hit the button at the top to stop the loading effect.<br />
<br />
The latest code can be found at:<br />
<a href="https://github.com/dshefman/FlexSparkDataGridSpannableColumns" target="_blank">https://github.com/dshefman/FlexSparkDataGridSpannableColumns</a><br />
<br />
<br />
There were a couple of things that I discovered was missing on <a href="https://github.com/dshefman/FlexSparkDataGridSpannableColumns/blob/master/com/squaredi/grids/sparkdatagrid/columnSpanning/renderers/ColumnSpanningGridItemRenderer.as">ColumnSpanningGridItemRenderer</a>:<br />
<br />
<ol>
<li>Setting the new data to a cell needed to reset the expanded cell</li>
<li>I created a function called getSpanData() that by default returns data, but could be overwritten if there were nested data structures that was the span data</li>
<li>I added bubbling events, so that the grid could respond to spanning and non-spanning changes as well. </li>
</ol>
<h3>
****Performance Warning*****</h3>
<div>
There is a performance hit with this spanning solution. You can see it when you scroll. The calculations to determine if spanned and then to reparent and reposition the span takes a toll. Especially if there are alot of spans. For us, that was an acceptable solution, especially since we could rationalize that "it was loading", so of course it is busy doing other things :) </div>
<div>
<br /></div>
<div>
If you can make it faster, please contribute back on Git. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com0tag:blogger.com,1999:blog-7392132758872548721.post-90966871583419501822013-02-11T17:28:00.000-08:002013-02-11T17:28:16.812-08:00Flex GridColumn, complex objects, and default sortingI recently discovered something about the spark GridColumn. You can pass in a complex type for the dataField.<br />
<br />
Say for example that your dataProvider is a collection of Users:<br />
<br />
<pre class="brush:as3">public class User
{
public var name:String;
public var id:String;
public var manager:User;
}
</pre>
<br />
<br />
You can specify the gridColumn.datafield as "manager.name"<br />
<pre class="brush:text"><s:GridColumn dataField="manager.name" /></pre>
<br />
This is really cool. Can you can see it in the <a href="https://svn.apache.org/repos/asf/flex/sdk/trunk/frameworks/projects/spark/src/spark/components/gridClasses/GridColumn.as" target="_blank">source code</a> down where the datafield property is set. There is an internal dataFieldPath variable.<br />
<br />
Here is the problem that I ran into. I had several columns that had these nested values and I wanted to set up each column to have case insensitive sorting, which is not the default. Using a shared sortFunction was difficult, because I also didn't have direct acces to the dataFieldPath (the nested property), and it would have too much work (in my opinion) to build the object within the sort and then grab the string and then lowercase and compare. It was especially too much work, because it would have negated any label functions that were already in place for these columns. <br />
<br />
So here is my solution:<br />
<br />
<br />
<pre class="brush:as3">package com.workbook.core.view.datagrid
{
import mx.formatters.IFormatter;
import spark.collections.SortField;
import spark.components.gridClasses.GridColumn;
import spark.components.gridClasses.GridSortField;
public class CaseInsensitiveComplexDataPathGridColumn extends GridColumn
{
public function CaseInsensitiveComplexDataPathGridColumn()
{
super()
}
override public function get sortField():SortField
{
var sf:SortField = super.sortField;
const isComplexDataField:Boolean = sf is GridSortField;
var cF:Function = null;
if (isComplexDataField && sortCompareFunction == null)
{
sf.compareFunction = dataFieldPathSortCompareCaseInsensitive;
}
return sf;
}
protected function dataFieldPathSortCompareCaseInsensitive(obj1:Object,
obj2:Object):int
{
if (!obj1 && !obj2)
return 0;
if (!obj1)
return 1;
if (!obj2)
return -1;
const obj1String:String = itemToLabel(obj1).toLowerCase();
const obj2String:String = itemToLabel(obj2).toLowerCase();
if ( obj1String < obj2String )
return -1;
if ( obj1String > obj2String )
return 1;
return 0;
}
}
}</pre>
<br />
What this does, is that when you click on the column header, it grabs the sortfield from the gridColumn (that was the easiest public property to get at). Fortunately if the dataField is complex, it builds a GridSortField object instead of a SortField.
<br />
<br />
I check for the GridSortField and if there is not already a sortCompareFunction, I assign it to my case insensitive sort function.<br />
<br />
Then within the sort function, I call itemToLabel, which fortunately does all of the heavy lifting to determine the nested object's label, calling any labelFunctions as needed.<br />
<br />
Then I force to lowercase, and done.<br />
<br />
To use, I replace my GridColumn in my dataGrid definition, with CaseInsensitiveComplexDataPathGridColumn.dShefmanhttp://www.blogger.com/profile/13536061718008158529noreply@blogger.com5