Adrian Unger https://staydecent.ca/ Hi there, I’m Adrian Unger, a software developer who prefers to be outdoors. 2022 2022: Year in Review Adrian Unger Wed, 28 Dec 2022 00:00:00 -0800 https://staydecent.ca/blog/2022-year-in-review https://staydecent.ca/blog/2022-year-in-review <p>Well, I didn't blog for a whole year. My last post was a <a href="/blog/2021-year-in-review">reflection on 2021</a> where I left off saying &quot;For now, I’m still feeling introspective and perhaps in waiting. For what, I can’t say—though I have some ideas. Yet, I sense a new beginning in 2022.&quot; So, let's start there!</p> <p>Indeed, that introspection continued in what I guess I would call my path towards spirituality. I struggle to share with people that I'm now a &quot;spiritual person&quot; or &quot;on the spiritual path&quot; without sounding like a dork. Oh well 🤷‍♀️. This has mostly been guided by books, podcasts, and the wisdom of <a href="http://hapaway.com/">my partner</a>.</p> <p>As for the new beginning: my partner and I sold our house and moved to a new town! This decision was largely guided by intuition and spiritual guidance rather than reason, which has resulted in a jolt of exuberance in both of our lives. There seem to be certain moments, at least in my life, where a life decision presents itself with two main paths: the first being one of reason and rationality, which garners support by friends, family, and even society at large; the other is one that eschews reason, yet pulls on you despite all the reason you throw at it. When debating internally, you often refer to the reasonable option as the one you &quot;should&quot; choose. The other option is the one you &quot;want&quot; for seemingly inexplicable reasons. In my experience, following the second path consistently leads to unknown outcomes that exceed whatever I could have dreamed of.</p> <p>Otherwise, world events and other external matters played a smaller role for me in the last year. I have forgone social media and news in favor of the aforementioned spiritual and personal growth. Which, I believe, allows me to remain open and compassionate regardless of the situation at hand. I am deeply grateful for my current circumstance that allows personal growth to be such a focus at this time in my life.</p> <h2>Some Favourites from 2022</h2> <p>I plan to share a bit of an outlook on 2023 in a future post. To wrap up 2022, I wanted to reflect on some memorable books, podcasts, videos, and other <em>content</em> that stood out to me.</p> <h3>Books</h3> <p>I don't really rate books. If I finish a book, then I'd give it a 4 or 5 stars. Anything less, and I wouldn't have finished the book. So, any book I finish is a book I would highly recommend!</p> <ul> <li><a href="https://isbnsearch.org/isbn/9781622037520">Alan Watts - Out of Your Mind</a>: Some of Alan Watts most revered lectures compiled into a book by his Son. An enjoyable introduction to Watts and some tenets of Buddhism from his perspective.</li> <li><a href="https://isbnsearch.org/isbn/9780525512547">Yongey Mingyur Rinpoche - In Love with the World</a>: Interesting to learn about the early life of someone who grew up in Tibetan Buddhism from birth and the eventual wandering meditation they took on that nearly led to their death.</li> <li><a href="https://isbnsearch.org/isbn/9780874774924">Kathleen Riordan Speeth - The Gurdjieff Work</a>: Ah, the &quot;rascal sage&quot; who was perhaps one of the first people to integrate &quot;Eastern&quot; and &quot;Westen&quot; wisdom for European and American <em>seekers</em>. <em>The Work</em> is an interesting system with many aspects applicable in our modern times. Fun, yet heavy reading.</li> <li><a href="https://isbnsearch.org/isbn/9780671732479">Carlos Castaneda - The Second Ring of Power</a>: Really, I recommend the whole Don Juan series by Carlos Castaneda. I think I've read nine of the eleven books he wrote on the teachings of Don Juan. The teachings are quite esoteric, and would likely require a lifetime dedication to fully integrate. While all of the books are interesting in their own right, I'd say The Second Ring of Power had the most gripping tale.</li> <li><a href="https://isbnsearch.org/isbn/9781570629570">Chögyam Trungpa - Cutting Through Spiritual Materialism</a>: For anyone interested in spirituality, I'd recommend this as a must-read. Compiled from lectures that Chögyam Trungpa gave in the 1970s, advising on how the spiritual path, if jumped into naively, can actually reinforce the ego leading to hardened egocentricity. I will likely reread this over the years.</li> </ul> <h3>Podcasts</h3> <p>I don't really listen to podcasts. Haha, however, when my partner are in the car for extended periods of time, we often throw on a podcast episode or two. This last year, <a href="https://www.ramdass.org/teachings/?fwp_format=podcast">Here and Now</a> by Ram Dass has been consistently good.</p> <h3>Skateboard Videos</h3> <p>After taking a decade away from skateboarding, I've been getting back into it over the last few years, with 2022 being the heaviest yet. That said, there is just way too much skateboard content to keep up -- and I'm not even on the 'gram! Anyway, here are some fav videos I bookmarked.</p> <ul> <li><a href="https://youtu.be/iYu0bUyeMO0">WKND - BOTTLE NECK SEWAGE</a></li> <li><a href="https://youtu.be/Yi0ERENViF4">Skateboarding X Rollerblading</a></li> <li><a href="https://youtu.be/6yDSHC0EPyc">Element Skateboards &quot;E.S.P. VOL.2&quot; Video</a></li> <li><a href="https://www.thrashermagazine.com/articles/videos/deedz-hvvs-part/">Deedz' &quot;HVVS&quot; Part</a></li> <li><a href="https://www.thrashermagazine.com/articles/videos/tyshawn-jones-the-general-hardies-part/">Tyshawn Jones’ “The General” Hardies Part</a></li> <li><a href="https://www.thrashermagazine.com/articles/videos/zero-introduces-kairi-netsuke/">Zero Introduces Kairi Netsuke</a></li> <li><a href="https://www.thrashermagazine.com/articles/videos/t-funk-s-deepfried-x-baker-part/">T Funk's &quot;Deep Fried X Baker&quot; Part</a></li> <li><a href="https://youtu.be/1avzYu_paZA">SOLO: Vincent Milou's &quot;You Changed&quot; video part</a></li> </ul> <h3>Movies</h3> <p>For context, I generally limit my movie watching to action-comedies and romcoms.</p> <ul> <li><a href="https://www.rottentomatoes.com/m/triangle_of_sadness">Triangle of Sadness</a>: Can I actually recommend this movie? I don't really know. It was entertaining. It was horrendous. I walked away with a empty pit of despair in my stomach.</li> <li><a href="https://www.rottentomatoes.com/m/bullet_train_2022">Bullet Train</a>: Some people seem to dislike the premise of the story. I thought it was hilarious.</li> <li><a href="https://www.rottentomatoes.com/m/everything_everywhere_all_at_once">Everything Everywhere All at Once</a>: I mean, come on.</li> <li><a href="https://www.rottentomatoes.com/m/the_lost_city">The Lost City</a>: Good ol' Holywood entertainment here.</li> <li><a href="https://www.rottentomatoes.com/m/bodies_bodies_bodies">Bodies Bodies Bodies</a>: I laughed.</li> <li><a href="https://www.rottentomatoes.com/m/confess_fletch">Confess, Fletch</a>: Other than action-comedies and romcoms, I also enjoy comedy/mystery movies.</li> <li><a href="https://www.rottentomatoes.com/m/vengeance_2022">Vengeance</a>: Was it a good year for comedies or something?!</li> </ul> <h3>YouTube Channels</h3> <p>lol, why not.</p> <ul> <li><a href="https://www.youtube.com/@dianxixiaoge">Dianxi Xiaoge</a>: Peaceful and beautiful channel about food from a small town in Yunnan, China.</li> <li><a href="https://www.youtube.com/@KurtCaz">Kurt Caz</a>: If &quot;Gonzo Travel YouTuber&quot; is a thing, I'd venture Kurt embodies that perfectly.</li> <li><a href="https://www.youtube.com/@gasgiants2028">Gas Giants</a>: Best &quot;Skating with Friends&quot; type YT channel out there.</li> </ul> <p>Okay, I'm bored if this. Happy new year!</p> 2021: Year in Review Adrian Unger Fri, 31 Dec 2021 00:00:00 -0800 https://staydecent.ca/blog/2021-year-in-review https://staydecent.ca/blog/2021-year-in-review <p>It was a year of quiet introspection and growth. In the Pacific Northwest, we experienced <a href="https://csanr.wsu.edu/what-can-we-learn-from-the-pacific-northwest-heat-dome-of-2021/">record heat</a>, <a href="https://www.theprogress.com/news/class-action-lawsuit-filed-to-recoup-losses-from-sumas-prairie-flooding-in-abbotsford/">flooding</a>, and <a href="https://nanaimonewsnow.com/2021/12/26/heavy-snow-frigid-temperatures-paralyze-nanaimo-oceanside-region/">snow</a>. The garden has come into its own, supporting a budding ecosystem that invites ever more bees, birds, rabbits, deer and snakes. </p> <p>As for the pandemic, it was if anything enlightening. It seems no lessons were learned along the way and public policy embodied the sunk-cost fallacy. Just keep doubling down despite poor outcomes. Why have we been <a href="https://bc.ctvnews.ca/shut-out-of-free-take-home-kits-some-british-columbians-buying-their-own-rapid-tests-1.5709462">sitting on millions</a> of <a href="https://www.theglobeandmail.com/politics/article-millions-of-covd-19-rapid-tests-sitting-unused-records-show/">rapid antigen tests</a>? Why didn’t we utilize them ASAP for <a href="http://www.phsa.ca/current-outbreaks">long term care homes</a>? Why do public figures continue to lie about <a href="https://staydecent.ca/blog/do-the-mrna-vaccines-prevent-transmission/">preventing transmission</a>? Who knows. Be it <a href="https://www.gutenberg.org/ebooks/445">mass hysteria</a> or mass incompetence, I believe our representatives have good intentions. However, it still elucidates the short comings of a stagnant beast, that is ill fitted for efficiency and adaptation. If a system that generates <a href="https://www.fraserinstitute.org/sites/default/files/growing-debt-burden-for-canadians-2021.pdf">hundreds of billions in debt</a> can’t produce better results then we need to rethink the core structures that keep this berg afloat. </p> <p>Or, at least I’ve been rethinking these systems as a citizen. I’m damn near 50% of my income being taxed. Canada has long been ranked as one of the <a href="https://www2.deloitte.com/content/dam/Deloitte/global/Documents/Public-Sector/dttl-ps-govtefficiency-08082013.pdf">least</a> <a href="https://www.mckinsey.com/~/media/McKinsey/Industries/Public%20and%20Social%20Sector/Our%20Insights/The%20opportunity%20in%20government%20productivity/Government-Productivity-Unlocking-the-3-5-Trillion-Opportunity-Full-report.pdf">efficient</a> governments on this here planet and it’s high time we address that rather than throw more money into the pit. </p> <p>Beyond the societal systems we currently exist within I’ve also been expanding my internal systems. I’ve found an agreeable resonance with the words of Henry Miller, don Miguel Ruiz Jr., Richard Rudd, Eckhart Tolle, Carlos Castaneda, and John Berger. I seem to have slipped into a groove of being introduced to books that consistently expand my thinking and leave me feeling more calm and acceptant of our human experience. </p> <p>For now, I’m still feeling introspective and perhaps in waiting. For what, I can’t say—though I have some ideas. Yet, I sense a new beginning in 2022. Some sort of life changing event or circumstance. How exciting!</p> Do the mRNA Vaccines Reduce or Prevent Transmission? Adrian Unger Sat, 13 Nov 2021 00:00:00 -0800 https://staydecent.ca/blog/do-the-mrna-vaccines-prevent-transmission https://staydecent.ca/blog/do-the-mrna-vaccines-prevent-transmission <p>I struggle to understand the messaging around the vaccines and what they are purported to do, and how mask mandates seem contrary to a vaccine mandate, especially when it results in firing healthcare workers.</p> <p>First, I think it will be helpful to understand my current conclusion as I will likely, unintentionally, view the following studies and sources with this bias. Knowing my bias, I hope people can elucidate me in places where I may be misunderstanding or misrepresenting the data.</p> <p>My current conclusion is that the mRNA vaccines are effective at reducing transmission, and hospitalization (aka severe-illness), in the <em>short term</em>. I have not seen any evidence they reduce death, and it seems that both reduction in transmission and hospitalization wanes somewhere in the 3-9 month range, with reduction of transmission waning sooner than hospitalization.</p> <h2>What Does the CDC Say?</h2> <p>As the CDC is a Public Health Organization (PHO) where it's decisions carry weight across other PHOs, I think it's a good place to start.</p> <p><a href="https://www.cdc.gov/mmwr/volumes/70/wr/mm7034e4.htm">Effectiveness of COVID-19 Vaccines in Preventing SARS-CoV-2 Infection Among Frontline Workers Before and During B.1.617.2 (Delta) Variant Predominance — Eight U.S. Locations, December 2020–August 2021</a></p> <p>This study confirms that between December 14, 2020–April 10, 2021, the vaccines were &quot;approximately 90% effective in preventing symptomatic and asymptomatic infection with SARS-CoV-2.&quot; That is a five-month period. From April 10-August 14, Vaccine Efficacy (VE) declined to 66% which was the period in which the Delta variant became dominant. But, they conclude &quot;VE might also be declining as time since vaccination increases and because of poor precision in estimates due to limited number of weeks of observation and few infections among participants.&quot;</p> <p>So, efficacy wanes after 5 months, and we aren't too sure why--it could be time since vaccination, Delta, or perhaps both. I'd also say, as this study looks at around ~5000 frontline workers in 6 different healthcare locations, it may not be fully representive.</p> <p>Even more interesting, is this study was published by the CDC on August 24, 2021, even though CDC Director Rochelle Walensky in an interview with CNN, can be <a href="https://www.realclearpolitics.com/video/2021/08/06/cdc_director_vaccines_no_longer_prevent_you_from_spreading_covid.html">seen saying</a> &quot;[the vaccines] continue to work well with delta with regard to severe illness and death, but what they can't do anymore is prevent transmission.&quot; This was said on August 6th, 2021. So, the vaccines &quot;work well&quot; but don't prevent transmission?</p> <h2>Did the Vaccines Ever Prevent Transmission?</h2> <p>Well, back in December 2020, <a href="https://aid.uw.edu/faculty/lawrence-corey-md">Dr. Larry Corey</a> of the University of Washington who is a Professor of the Department of Laboratory Medicine &amp; Pathology, and member of the Division of Vaccine &amp; Infectious Disease (VIDD), <a href="https://coronavirus.jhu.edu/vaccines/blog/the-messenger-rna-vaccines-and-masks">didn't think so</a>. </p> <blockquote> <p>Current phase 3 trials tell us whether COVID-19 vaccines prevent illness and hospitalization, but not whether the vaccines prevent infection and transmission. Additional studies will need to be done, perhaps within households and on college campuses, to see whether COVID-19 vaccines prevent virus transmission, allowing us to return to a more normal life.</p> </blockquote> <p>If we look at the <a href="https://www.fda.gov/media/144245/download">Pfizer and BioNTech FDA Briefing Document</a> from December 10, 2020, we can see &quot;Data are limited to assess the effect of the vaccine against transmission of SARS-CoV-2 from individuals who are infected despite vaccination.&quot;</p> <p>I'd argue that the data Pfizer and BioNTech provide to the FDA to get Emergency Use Authorization can be considered good primary data. And this primary data does not indicate a reduction in transmission. So, none of the early trials that lead to the vaccines getting authorized looked at transmission. Why then, did our public health officials tell us that getting the vaccine would protect our community? That it would protect the vulnerable and immunocomprimised?</p> <h2>But There Must Be Studies Suggesting a Reduction in Transmission, No?</h2> <p>Indeed, there are more recent studies. One <a href="https://www.medrxiv.org/content/10.1101/2021.10.14.21264959v1.full-text">pre-print from the Dutch Ministry of Health</a> (meaning the study has not been peer-reviewed or published by a Journal yet), claims &quot;Our results indicate that vaccination confers protection against onward transmission from vaccinated index cases, albeit somewhat less for Delta than for Alpha.&quot; But comes with the caveat, &quot;Possible waning of vaccine effectiveness against infection and against onward transmission could result in increases in SARS-CoV-2 circulation among populations with high vaccine coverage.&quot;</p> <p>[Update Nov 18, 2021] I found another recent study on transmission by scouring Google Scholar, <a href="https://www.nejm.org/doi/full/10.1056/nejmc2106757">Effect of Vaccination on Transmission of SARS-CoV-2</a>. The aim of the study was to look at the effect of vaccination of health care workers and the risk of COVID-19 among their household members. Outcomes were determined by &quot;any confirmed case of Covid-19 that occurred between December 8, 2020, and March 3, 2021&quot;. So, 85 days, which is not a very long period. The <a href="https://www.nejm.org/doi/suppl/10.1056/NEJMc2106757/suppl_file/nejmc2106757_appendix.pdf">supplementary appendix</a> indicates the health care cohort only includes 18-65 year olds, while the household cohort includes all ages, which they acknowledge: &quot;We are therefore unable to evaluate the impact on vaccinating elderly or vulnerable individuals.&quot; Anyway, the study concludes (emphasis mine):</p> <blockquote> <p>Given that vaccination reduces asymptomatic infection with SARS-CoV-2, it is plausible that vaccination reduces transmission; however, data from clinical trials and observational studies are lacking. We provide empirical evidence <em>suggesting</em> that vaccination <em>may</em> reduce transmission by showing that vaccination of health care workers is associated with a decrease in documented cases of Covid-19 among members of their households. This finding is reassuring for health care workers and their families.</p> </blockquote> <p>So, in a period of 85 days, or less than 3 months, there <em>may</em> be a reduction of transmission in the vaccinated. One, this isn't very compelling evidence. Two, this was published on Oct 28, 2021, meaning it could not have informed public health policy.</p> <p>Another <a href="https://www.thelancet.com/journals/laninf/article/PIIS1473-3099(21)00648-4/fulltext">study recently published in The Lancet</a> concludes &quot;fully vaccinated individuals with breakthrough infections have peak viral load similar to unvaccinated cases and can efficiently transmit infection in household settings, including to fully vaccinated contacts.&quot; More than that, a prominent pro-vaccine figurehead, Bill Gates <a href="https://www.youtube.com/watch?v=CZplF4qdwII&amp;t=1610s">recently said</a> &quot;we didn't have vaccines that block transmission..&quot; I don't know why he uses the past-tense, but intereresting nonetheless.</p> <h2><a href="https://www.youtube.com/watch?v=QRt2_OLY3Ho">But, what does it all mean Basil?!</a></h2> <p>Well, it seems like transmission was never prevented nor significantly reduced. Which, to me, means we can leave out transmission as a characteristic of determining if the vaccines make sense or not for different people. Further, since these mRNA vaccines don't prevent transmission, the vulnerable and immunocomprimised are not protected by those who opt to get the vaccine. Which is why public health officials are mandating mask wearing, as we try to actually reduce transmission.</p> <p>But, why mandate the vaccine? Or, more specifically, why do our Provincial and Federal mandates only push the vaccine rather than the more sensical <a href="https://www.thelocal.dk/20210528/denmark-launches-new-corona-passport-heres-what-you-need-to-know-about-coronapas-app/">covid passports</a> of European countries? Since transmission is not reduced by the vaccine, should we not be opting for negative test results? Especially rapid-antigen tests? As well as counting <a href="https://brownstone.org/articles/natural-immunity-and-covid-19-twenty-nine-scientific-studies-to-share-with-employers-health-officials-and-politicians/">natural immunity</a>? It seems pretty clear, that relying solely on <a href="https://globalnews.ca/news/8335126/fully-vaccinated-hockey-league-covid-outbreak/">vaccination status</a> is <a href="https://www.cbc.ca/sports/hockey/nhl/ottawa-senators-games-postponed-covid-19-outbreak-1.6249618">not enough</a> to <a href="https://thehill.com/policy/transportation/569185-cruise-passenger-dies-of-covid-19-amid-outbreak-on-ship">stop transmission</a>.</p> <p>This is very confusing, especially at a time when social media sites are banning accounts that spread misinformation, such as <a href="https://blog.youtube/news-and-events/managing-harmful-vaccine-content-youtube/">YouTube which removes videos</a> that include &quot;claims that vaccines do not reduce transmission&quot;...Why?! I could quote the Pfizer document to the FDA and be in violation of &quot;misinformation guidelines&quot;?</p> <p>Where did people even get the idea that these treatments would reduce transmission when there hasn't been data to back it up? Moreover, I don't understand why our governments are limiting the tools we could use to mitigate the effects of this disease, especially to those who are most vulnerable. How does firing health care workers who remain unvaccinated make any sense, if the vaccine doesn't reduce transmission? Am I missing something?</p> Experts Think You're Too Stupid For Data Adrian Unger Sun, 17 Oct 2021 00:00:00 -0700 https://staydecent.ca/blog/experts-think-you-re-too-stupid-for-data https://staydecent.ca/blog/experts-think-you-re-too-stupid-for-data <p>Recently, Alberta Health attributed their youngest COVID-19 related death to a 14-year old boy. This triggered the family of the 14-year old to <a href="https://westernstandardonline.com/2021/10/sister-of-dead-14-year-old-boy-blasts-ahs-for-labelling-his-death-covid-related/">criticize the reporting</a>, calling it &quot;fake news.&quot;</p> <p>Days later, Alberta's Chief Medical Officer, retracted the death from their covid count making a <a href="https://www.cbc.ca/news/canada/edmonton/hinshaw-apologizes-to-family-of-14-year-old-after-saying-he-died-from-covid-19-1.6210691">half-apology</a>. What's concerning here, is that in the aftermath we aren't seeing a push for more data or even more accurate data. Instead, we are seeing &quot;experts&quot; argue that comorbidities should not be made public, as it may &quot;undermine the public's understanding of the disease.&quot;</p> <p>In what reality does withholding information create a better understanding of anything?</p> <p>But, before we get to that, we need to look at how the CBC is still reporting &quot;fake news.&quot; Or, at least egregiously incorrect news.</p> <p>In a <a href="https://www.cbc.ca/news/canada/edmonton/covid-comorbidities-alberta-spitzer-1.6212510">recent update</a> around the reporting of Nathanael Spitzer's death, CBC journalist Wallis Snowdown writes:</p> <blockquote> <p>Hinshaw announced the province will no longer report COVID-19 deaths of children until a review process has been completed to confirm the actual cause of death.</p> </blockquote> <p>Then, about 7 or 8 or sentences later, Snowdon writes:</p> <blockquote> <p>After a COVID-19 death is reported, each case is assessed to ensure the reporting is accurate. If fault is found, the case is removed from Alberta's COVID-19 statistics.</p> </blockquote> <p>No. Clearly each case is not accurately assessed. That is the impetus of why you are even reporting on this! Especially, when you quote Hinshaw announcing that they will <em>now</em> review cause of death in children.</p> <p>Snowdon then goes on to assume that releasing data around comorbidities will result in this faulty conclusion:</p> <blockquote> <p>Pre-existing conditions can range from severe to minor — and just because someone has a comorbidity does not mean they were likely to die before contracting COVID-19.</p> </blockquote> <p>Of course not! Why are you making that assumption? Why are you assuming the public will make that assumption? Terminal Brain Cancer is not the same thing as having Diabetes. But, in either case, we can say that, statistically, you are more at risk of hospitalization and death if you contract COVID-19 and have underlying health conditions. This association has been made all <a href="https://www.aljazeera.com/features/2021/5/24/comorbidities-and-covid-a-much-higher-risk-of">around</a> <a href="https://europepmc.org/article/PMC/PMC8224257">the</a> <a href="https://archive.is/evf9d">world</a>.</p> <blockquote> <p>[Dr. Noel Gibney, professor emeritus in the department of critical care medicine at the University of Alberta in Edmonton] said tracking comorbidities can contribute to a broader understanding of the pandemic, but sharing the data publicly is problematic.</p> </blockquote> <p>The public cannot be trusted with data around comorbidites... Wow. These elite academic types must think very little of the general public.</p> <blockquote> <p>[..] the data also stigmatizes those with underlying health conditions.</p> </blockquote> <p>Further, Ubaka Ogbogu, an associate professor in the faculty of law and the Katz Research Fellow in Health Law and Science Policy at U of A, joins in on this sentiment:</p> <blockquote> <p>People who have these comorbidities are going to live in fear.... And that anxiety is not being matched by any action from these governments to actually show that they're trying to protect those who are especially vulnerable.</p> </blockquote> <p>What? This entire Country is living in fear! Why else would fully vaccinated individuals be wearing a <a href="https://wwwnc.cdc.gov/eid/article/26/10/20-0948_article">cloth face mask</a> <a href="https://news.yahoo.com/cdc-director-defends-agency-inflated-200906002.html">outdoors</a>? </p> <p>When COVID-19 hospitalization and death data is stratified by age and comorbidities, it highlights the reality of who is at risk. There is nothing wrong with these people in a social context. I have yet to see anyone stigmatize people suffering from cancer or heart disease, or for ageing. Is this stigmatization so prevalent that we should indeed withold information from the public?</p> <p>Prior to COVID-19, is was quite normal to acknowledge that immunocompromised individuals were at <a href="https://pubmed.ncbi.nlm.nih.gov/29485353/">high risk of complications from influenza infection</a>. What has changed since then? </p> <p>Having this data available allows the public (and researchers!) to compare and analyze outcomes from around the world, painting a clearer picture of the characteristics of COVID-19 and how it's affected by underlying health conditions. This helps the public to better understand their own risk profile, and could inform more targeted interventions in order to avoid lockdowns and mandates in the future.</p> <p>In contrast, these experts believe that data from a publicly funded institution should not be made public because they fear that the public may interepret the data in a way that does not align with their narrative or interpretation.</p> How Policy Shifted The Burden of The Pandemic Adrian Unger Wed, 01 Sep 2021 00:00:00 -0700 https://staydecent.ca/blog/how-policy-shifted-the-burden-of-the-pandemic https://staydecent.ca/blog/how-policy-shifted-the-burden-of-the-pandemic <p>Our response to the Covid-19 pandemic has shifted hospitalizations and mortality from the over-65 to the under-65 age group. Social distancing, lockdowns, and masking are contributing to mental health epidemics, and affecting the immune systems of children.</p> <p>Under-65 excess mortality <a href="https://www150.statcan.gc.ca/n1/daily-quotidien/210712/dq210712b-eng.htm">exceeds under-65 Covid-19 deaths in Canada</a>. Approximately 90% of Covid-19 <a href="https://health-infobase.canada.ca/covid-19/epidemiological-summary-covid-19-cases.html?redir=1#a7">deaths are in the over-65 group</a>, yet 2020 saw the highest rates of accidental poisonings and overdoses for those under-65. The average age of Canadians who died of Covid-19 in 2020 is <a href="https://www150.statcan.gc.ca/n1/pub/91f0015m/91f0015m2021002-eng.htm">83.8 years</a>, while the average age at death in Canada in 2019 was 76.5 years.</p> <p>Anyone, regardless of age, dieing from Covid-19 is a tragedy. But, the policies and response to Covid-19 should not result in an increase in mortality among the under-65! And, it's not like we have to start from scratch, nor guess how we should be addressing the pandemic. <a href="https://gbdeclaration.org/">The Great Barrington Declaration</a>, written by infectious disease epidemiologists and public health scientists, lays out how focused protection can be effective.</p> <p>Further, the damage we are doing to children, by limiting their exposure to other pathogens by social distancing and mask wearing could drastically <a href="https://www.cmaj.ca/content/193/29/E1140">shift mortality rates</a>. Respiratory Syncytial Virus (RSV) hospitalizations among children in Canada range from 6000 to 12,500[1] per year. Covid-19 has only seen 1,489 <em>under-19s</em> hospitalized! Average RSV hospitalizations are at least 6x that of Covid-19! Does our response feel proportional?</p> <p>We don't have a clear picture of all the possible effects of our pandemic policies. And, we're already seeing signals with increased excess mortality in the young, and limited immune exposure in infants. Does it make sense to shift the burden of the pandemic on to the young?</p> <h5>Footnotes</h5> <p>[1] Within USA, 100,000 hospitalizations and 4,500 deaths annually are <a href="https://www.canada.ca/en/public-health/services/laboratory-biosafety-biosecurity/pathogen-safety-data-sheets-risk-assessment/respiratory-syncytial-virus.html#endnote2">attributed to RSV</a>. In developed countries, <a href="https://www.cps.ca/en/documents/position/preventing-hospitalizations-for-rsv-infections">1% to 3% of all infants</a> are hospitalized with RSV infection. The exact numbers for Canada are behind a paywalled study, but <a href="https://storage.googleapis.com/staydecent/blog/Screenshot%202021-09-01%20081358.jpg">Google surfaces the details</a>.</p> It's Not Us Vs. Them, Pandemic Edition Adrian Unger Sun, 29 Aug 2021 00:00:00 -0700 https://staydecent.ca/blog/it-s-not-us-vs-them-pandemic-edition https://staydecent.ca/blog/it-s-not-us-vs-them-pandemic-edition <p>Early on in the Pandemic, it was all &quot;we're in this together!&quot; &quot;two weeks to flatten the curve!&quot; &quot;We love our frontline workers!&quot;. That message of unity and positivity has declined. Shifting, instead, to &quot;anti-vaxx&quot; vs &quot;pro-vaxx&quot;. Moreover, our government is infringing on our <a href="https://www.jccf.ca/wp-content/uploads/2021/08/Justice-Centre-Understanding-your-rights-and-freedoms.pdf">Charter Rights and Freedoms</a> in order to manage the ongoing pandemic. Why is that?</p> <p>I hope sharing my personal experience will explain why this situation is not black-and-white. And, that there is a lot of uncertainty and nuance which leaves room for differing opinions. Which is to say, I have some skepticism with the novel mRNA vaccines[1]. </p> <p>Anyway, I had fear in 2020. I thought some people were under-reacting. I thought those protesting mask mandates were petty. I was very wrong. But, this lead my to getting my first dose of Pfizer. While I did not have a serious adverse reaction, I did have an experience unlike prior vaccinations. Yes, I get vaccines. Being skeptical about the novel mRNA vaccines or the novel situations we find ourselves in does not mean one is anti-vaxx. If that has been your assumption over the last year you should ask yourself why.</p> <p>Back to my experience. It was only a few years ago that I got my booster for tetanus. This vaccine has generally been in use since WWII. It is a typical vaccine, which introduces a dead or weakened bacteria into your system. And, I garden and have cuts on myself all the time (from skateboarding etc.). The risk benefit ratio is pretty easy on this. I had zero effects other then minor soreness at the site of injection for a couple days. </p> <p>With Pfizer my whole arm muscle was sore and when used in some way the muscle would hurt and feel weak. Moreover, I experienced fatigue and struggled with cardio. Only recently, have I felt I have full-energy and health. I can't say that the jab caused this. Nor, can I say that catching SARS-CoV-2 wouldn't have been worse. But, it was enough that I had questions. Then there was the red marks, sorta like hives that appeared on my torso… anyway…</p> <p>Shortly after the first dose, I stumbled on the <a href="https://podcasts.apple.com/us/podcast/80-what-covid-reveals-about-our-leaders-bret-weinstein/id1471581521?i=1000521865103">dark horse podcast</a>. It touched on the suppression of ivermectin. Which is still going on today. Look, if you want to read <a href="https://www.rollingstone.com/politics/politics-news/fda-horse-dewormer-covid-fox-news-1215168/">rolling stone magazine</a> for your health and medical knowledge, so be it. But, it requires more personal work to glean out facts. Listening to podcasts is also not enough. Yet, many of these podcasts or people being labeled anti-vaxx provide sources and <a href="https://ivmmeta.com/">links</a> to confirm what they are saying. I’ve seen more <a href="https://pubmed.ncbi.nlm.nih.gov/34377451/">data</a> and <a href="https://pubmed.ncbi.nlm.nih.gov/33418230/">sources</a> shared by supposed anti-vax people then by politically appointed health officials. The latter who very often <a href="https://www.msn.com/en-us/news/us/fauci-said-masks-not-really-effective-in-keeping-out-virus-email-reveals/ar-AAKCZ0c">waffle</a> on what they say with little to no <a href="https://www.businessinsider.com/who-no-transmission-coronavirus-tweet-was-to-appease-china-guardian-2020-4?op=1">thorough explanation</a> as to why. </p> <p>This got me digging. And I love to dig. It’s one of the things that makes me good at my job. And it’s not hard. Is it an experimental vaccine? Read the official FDA emergency use authorization. How good is it at reducing mortality Versus a control group? Read the <a href="https://www.medrxiv.org/content/10.1101/2021.07.28.21261159v1.full-text">Pfizer preprint</a> (beyond the abstract). Is ivermectin only for horses? Read pretty much <a href="https://en.wikipedia.org/wiki/Ivermectin">anything</a> <a href="https://apps.who.int/iris/handle/10665/325771">other</a> <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7709596/">than</a> journalism. Who is at risk of death from COVID 19? Look up the data for your region. If your region doesn’t provide age stratified death rates then ask them to. Until then, look it up for another region that does. Same goes for <a href="https://www.bloomberg.com/news/articles/2020-03-18/99-of-those-who-died-from-virus-had-other-illness-italy-says">comorbidities</a> and <a href="https://www.cdc.gov/mmwr/volumes/70/wr/mm7010e4.htm">BMI</a>. Search for official data for specific regions. Unfortunately the latter is harder to find which is also absurd. </p> <p>Stop using journalism as the input for your personal determination of risk and fear. Yes, there will always be outlier cases that can stoke fear. Look at the data and make a risk-benefit analysis for yourself without the emotional toll that journalism evokes. </p> <p>I’m also not anti-journalism. But, there is a wide range of quality being published. And, for me, it's becoming more difficult to weed out cruft from unbiased reporting. This is troubling, because we need good reporters to question our political leaders. Yet, everything today is put into boxes and labeled. It's left vs right, progressives vs racists, anti-vaxx vs pro-science. We are failing to look at things objectively and with nuance.</p> <p>I'm concerned how people are turning on their neighbours over a novel vaccine. BCs pandemic plan aimed for <a href="https://www2.gov.bc.ca/gov/content/covid-19/info/restart">more than 70% of the 18+ population vaccinated with dose 1</a>. Why are we freaking out now that we’ve made it there (with two-doses no less!)? Are nurses quitting in droves? Does the immense <a href="https://news.harvard.edu/gazette/story/2021/08/wildfire-smoke-linked-to-increase-in-covid-19-cases-and-deaths/">forest fire smoke</a> we’ve had all summer <a href="https://www.cdc.gov/disasters/covid-19/wildfire_smoke_covid-19.html">play a part</a>? Was our health care system <a href="https://ccforum.biomedcentral.com/articles/10.1186/s13054-015-0852-6">already struggling</a>, and this past year pushed it over the edge? Is delta that much worse? Do masks make a difference[2]? And, <a href="https://nymag.com/intelligencer/2021/08/the-science-of-masking-kids-at-school-remains-uncertain.html">for children</a>? If you’re vaccinated aren’t you <a href="https://thehill.com/policy/transportation/569185-cruise-passenger-dies-of-covid-19-amid-outbreak-on-ship">safe</a>? Didn’t <a href="https://www.youtube.com/watch?v=y7C-59XFUFU">Bonnie Henry say mandates would be inequitable</a> (!!)? </p> <p>Mandates are a horrendously bad idea. More than that, our BC mandate is, in-fact, inequitable. Denmark's passport allowed for <a href="https://www.theguardian.com/world/2021/aug/27/denmark-to-lift-all-remaining-covid-restrictions-on-10-september">negative test results, natural immunity, or vaccine</a>. Why is ours only vaccination? Why are those with medical exemptions not accounted for? Why don’t we recognize <a href="https://www.sciencemag.org/news/2021/08/having-sars-cov-2-once-confers-much-greater-immunity-vaccine-no-infection-parties">natural immunity</a>? Why do we continue to punish <a href="https://www.pnas.org/content/117/30/17656#sec-9">small businesses</a> while simultaneously propping up <a href="https://www.propublica.org/article/how-the-coronavirus-bailout-repeats-2008s-mistakes-huge-corporate-payoffs-with-little-accountability">big corporations</a>? Why do we think it’s ever acceptable for the state to mandate medical interventions? What even is a <a href="https://archive.ph/2020.06.30-144032/https://twitter.com/TOPublicHealth/status/1275888390060285967?s=20">Covid-19 death</a>? Could <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4387051/">booster shots have their own risks</a>?</p> <p>Recently in Nova Scotia the <a href="https://www.pcpartyns.ca/solutions">Progressive Conservative</a> party won in an apparent upset. A key issue there was the struggling health care system (well before Covid) and they dug into why. Approximately, <a href="https://d3n8a8pro7vhmx.cloudfront.net/nspcparty/pages/1945/attachments/original/1627484020/Primary_Health_Plan_%281%29.pdf?1627484020">5% of Nova Scotians consume 70% of public health spending</a>. Much of this spending and care is in relation to chronic illnesses: diabetes, heart disease, COPD, frailty, obesity, arthritis, etc.. The solution is to educate and provide programs to help people take their personal health into their own hands, reducing the burden on hospitals and workers.</p> <p>The mortality rate of COVID-19 is significantly impacted by <a href="https://www.jpost.com/health-science/can-what-you-eat-save-you-from-covid-19-analysis-677426">BMI</a> and <a href="https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/deaths/bulletins/deathsinvolvingcovid19englandandwales/deathsoccurringinapril2020#pre-existing-conditions-of-people-who-died-with-covid-19">underlying health conditions</a>. If the argument is to reduce pressure on our health care system, wouldn’t reducing preventable diseases have a greater impact than mandating a vaccine for a single virus? And, more impact without giving up your individual autonomy to the state? The Canadian Government recently <a href="https://www150.statcan.gc.ca/n1/daily-quotidien/210712/dq210712b-eng.htm">released an analysis</a> on excess mortality (outside of covid-19 deaths) and found that under-65 excess mortality <em>exceeds</em> under-65 Covid-19 deaths!</p> <p>I share all this, in hopes that it paints a more nuanced picture of our shared reality. Perhaps things are more confusing and complex than simply forcing everyone to take a single approach to the virus? Maybe we should be open to a <a href="https://www.forbes.com/sites/williamhaseltine/2021/08/11/israels-recent-surge-confirms-we-need-a-multimodal-strategy-to-fight-covid-19/?sh=20fa59c45b6e">multimodal</a> approach to managing this pandemic. Perhaps we shouldn’t adopt the divisive labels that the media prescribes to people? Maybe we shouldn’t be so quick to judge? Fear and division themselves are <a href="https://journals.sagepub.com/doi/full/10.1177/0002764218759576">threats to society</a>. Contrary to the notion of chaos after crisis, people, when self-organized, are actually <a href="https://journals.sagepub.com/doi/abs/10.1525/ctx.2002.1.3.21">civil and effective</a>.</p> <h5>Footnotes:</h5> <p>[1] Pfizer-BioNTech is NOT approved for use, rather <a href="https://www.fda.gov/media/144412/download">authorized</a> due to an emergency. The recent approval of COMIRNATY admits VAERS is not capable of properly assessing all risks of the vaccine and has ordered Pfizer to <a href="https://www.fda.gov/media/151710/download">complete those studies themselves by 2025-2027</a>. Hence, experiments are ongoing.</p> <p>[2] Canada's prior <a href="https://thecanadianencyclopedia.ca/en/article/canadas-pandemic-influenza-plan">Influenza Pandemic Plan</a> specifically calls out wearing masks &quot;of limited effectiveness and may provide a false sense of security.&quot; With no data on showing higher effectiveness with covid-19, why are masks lauded so much?</p> Secularisation and the Loss of Morality Adrian Unger Mon, 05 Jul 2021 00:00:00 -0700 https://staydecent.ca/blog/secularisation-and-the-loss-of-morality https://staydecent.ca/blog/secularisation-and-the-loss-of-morality <blockquote> <p>At first, the secularisation of the capitalist world during the 19th century elided the judgment of God into the judgement of History in the name of Progress. Democracy and Science became the agents of such a judgement.</p> <p>— John Berger</p> </blockquote> <p>Democracy and Science are amoral. So morality is left to the people. In liberal democracy, it's left to the individual. Without a higher source of morality (God), do we lose morality as a people?</p> <p>With this lack of a communal moral compass, we are left with &quot;The Rule of Law&quot; which people grasp onto. But, our laws are not necessaily moral, so abiding without lenience creeps into Authoritarianism.</p> Inequities of Bitcoin Adrian Unger Mon, 15 Feb 2021 00:00:00 -0800 https://staydecent.ca/blog/inequities-of-bitcoin https://staydecent.ca/blog/inequities-of-bitcoin <p>Massive energy use and the creation of e-waste have been talked about rather extensively in regards to BTC -- Still waiting on a decent rebuttal to those points -- but I haven't seen much said about the inherent inequities of BTC. So, I thought I'd share some thoughts on this.</p> <h2>Information asymmetry</h2> <p>The adoption of BTC results in inequities from day one. Over the last decade, BTC has only been aware to those in technical circles. This information asymmetry allows a select group of people to gather BTC at a lower value than others. Now, as BTC reaches mainstream, all those convinced they should join are at a massive disadvantage, as the value is thousand times more expensive -- All of those early adopters are now much like the <em>1%</em>.</p> <h2>From one system to another</h2> <p>Moreover, as miners are awarded with BTC, those who have existing access to massive amounts of real-estate, computer equipment, and cheap energy, are also awarded with BTC. That means, those who are already in an advantaged position outside of BTC, can also gain an advantage within BTC. I also see no reason not to suspect that the Governments of the world (like US and China) are actually operating the largest mines, thus cementing their continued control of power and wealth in the new system.</p> <p>There doesn't seem to be any characteristics of BTC that prevent hoarding of wealth in a minority group?</p> <h2>Slow transactions</h2> <p>Transactions can be quite slow with BTC. While this is obviously a negative characteristic in terms of usability, it also exposes another inequity baked into the system: Transactions can be sped up if you are willing to pay a higher <a href="https://en.bitcoin.it/wiki/Miner_fees">miner fee</a>.</p> <p>That means those who hold more BTC, and thus can expend more of it without concern, can pay for faster transactions than the dispossessed. This is awful. Can you imagine a scenario where supply of something is limited, so there is a rush to buy? Would seller's not be incentivized to accept buyers whose transactions could happen in hours rather than days?</p> <p>Even for something like condo sales in a city with limited supply. While today, you may have to wait in lines overnight, or make offers with less conditions, or even make an offer without seeing a place... With BTC, would a seller not give preference to those who can prove they can afford the higher miner fees, thus closing a deal faster?</p> <p>What about the severely disposed? If I run out of food, and my transaction would take a day to process... Do I have to wait another 24 hours before eating?</p> <h2>Can these issues be fixed?</h2> <p>Will the underlying technology of BTC change to fix transaction times? Is there value loss if masses of BTC holders transfer to alternative networks or coins? Does that create another scenario of information asymmetry? How many times will people have to convert to a new coin until we are happy with the underlying technology?</p> <p>Could any change in the technology undo the massive lead that early adopters or large-scale miner operations have?</p> Energy Use of Bitcoin Adrian Unger Sun, 14 Feb 2021 00:00:00 -0800 https://staydecent.ca/blog/energy-use-of-bitcoin https://staydecent.ca/blog/energy-use-of-bitcoin <p>It seems proponents of BTC think that it actually has a net positive on the environment. Which is absurd to me, especially when the arguments are rather weak, and lack sources.</p> <div class="note">Update Feb 15, 2021: Here's a much better written analysis of Bitcoin energy use: <a href="https://www.ofnumbers.com/2021/02/14/bitcoin-and-other-pow-coins-are-an-esg-nightmare/" target="_blank">Bitcoin and other PoW coins are an ESG nightmare</a></div> <p>Perhaps, one could argue that the energy consumption of BTC is lower than what deterrents claim. But, proponents propose that BTC is actually a net positive for the environment! This misses the very large point that any energy increase is <a href="https://www.tandfonline.com/doi/abs/10.1080/13563467.2019.1598964?journalCode=cnpe20">contrary to a climate safe future</a>.</p> <blockquote> <p>there is no empirical evidence that absolute decoupling from resource use can be achieved on a global scale against a background of continued economic growth, and (2) absolute decoupling from carbon emissions is highly unlikely to be achieved at a rate rapid enough to prevent global warming over 1.5°C or 2°C</p> </blockquote> <h2>Comparing BTC to Gold</h2> <p>Conceptually, this is an interesting topic. But this is a misdirection. Comparing the entire historical impact of gold and fiat systems doesn't help us. We can learn from the past, but not undo it. Doesn't it make more sense to compare the annualized running costs of our fiat systems vs. that of BTC? Does the current annual running costs of gold backed currencies use more energy than BTC? Especially when you scale them to be 1-to-1? If BTC uses the energy of a small country today, what will it need if it were the global currency? Or even in use as much as the USD or Euro?</p> <p>The carbon footprint of a single BTC transaction <a href="https://digiconomist.net/bitcoin-energy-consumption#footprints">is 600,000 times that of a Visa transaction.</a> The Bitcoin Energy Consumption Index also estimates annualized consumption of 77.78 TWh. Further, the <a href="https://cbeci.org/">Cambridge Bitcoin Electricity Consumption Index</a> builds on criticisms of the BECI. Which finds annualized consumption at an even higher rate of 121 TWh!</p> <p>I have yet to find any peer-reviewed studies examining the energy use of our fiat systems. But, <a href="https://hackernoon.com/the-bitcoin-vs-visa-electricity-consumption-fallacy-8cf194987a50">this article claims</a>:</p> <blockquote> <p>So total consumption for [global] banks during a year only on those three metrics [servers, branches, atms] is around (I am rounding) 26Twh on servers, 58Twh on branches and 13Twh on ATMs for a total of close to a 100 Twh a year.</p> </blockquote> <p>Wow. Currently, the CBECI puts the annualized consumption of solely the BTC network at 121.19 TWh. If we added BTC ATMs, or data center consumption for exchanges and wallets, it would be even higher!</p> <p>While the environmental history of gold is bad, it should not serve as a baseline for what BTC can consume. Why should there be any leeway for continued environmental degradation and carbon emissions?</p> <h2>Questionable Sources</h2> <p>There are studies published outlining the excess energy use and e-waste of BTC. But, the criticisms always seem to be <a href="https://mobile.twitter.com/yassineark/status/1360343382556483587?s=21">tweet storms</a>.</p> <blockquote> <p>Bitcoin’s energy consumption is trivial compared to legacy financial systems. As measured by electricity costs alone, Bitcoin is much more efficient than traditional banking and gold mining on a global scale.</p> </blockquote> <p>That's incredible! But wait... are they comparing current Bitcoin use to that of the global financial systems? That's not a comparison at all, now is it? Well, let's check the source. Oh it's a <a href="https://danhedl.medium.com/pow-is-efficient-aa3d442754d3">Medium article</a>... One of the sources, links to another Medium <a href="https://medium.com/u/1852b393b452?source=post_page-----aa3d442754d3--------------------------------">author's homepage</a>, so not even a specific post. Great.</p> <p>Okay, finally it does link to something with some reputability. Which reports that the <a href="https://cseweb.ucsd.edu/~mbtaylor/papers/Taylor_Bitcoin_IEEE_Computer_2017.pdf">efficiency of ASICs</a> is slowing the rate of consumption as BTC grows. Sweet, but it's still adding the global energy use baseline? Oh, and those ASICs are single purpose electronics that have an <a href="https://www.cell.com/joule/fulltext/S2542-4351(19)30087-X?_returnURL=https%3A%2F%2Flinkinghub.elsevier.com%2Fretrieve%2Fpii%2FS254243511930087X%3Fshowall%3Dtrue">estimated lifespan of 1.5 years</a>!</p> <p>Have BTC proponents addressed the issue of the estimated <a href="https://www.cell.com/joule/fulltext/S2542-4351(19)30087-X?_returnURL=https%3A%2F%2Flinkinghub.elsevier.com%2Fretrieve%2Fpii%2FS254243511930087X%3Fshowall%3Dtrue#secsectitle0030">10,948 metric tons</a> of e-waste produced by mining operations?</p> <p>Many argue the benefit of a new currency outweighs the negative aspects of energy use and e-waste. But, I guess it depends what's more pressing or important to you? To accrue wealth in a new system, or to prevent 2 degree warming for our planet? Many are suggesting the latter may be more important...</p> <blockquote> <p>Fifty-one billion is how many tons of greenhouse gases the world typically adds to the atmosphere every year. Zero is what we need to aim for. To stop the warming and avoid the worst effects of climate change, humans need to stop adding greenhouse gases to the atmosphere. The climate is like a bathtub that’s slowly filling up with water. Even if we slow the flow of water to a trickle, the tub will eventually overflow. Setting a goal to reduce our emissions won’t do it. The only sensible goal is zero. -- <a href="https://www.theguardian.com/environment/2021/feb/13/bill-gates-on-the-climate-crisis-i-cant-deny-being-a-rich-guy-with-an-opinion">Bill Gates</a></p> </blockquote> <p>But, even before answering that. The most egregious claim by Dan Hedl:</p> <img src="/assets/media/table-with-no-sources.jpg" alt="A table containing numbers with no sources" /> <p>Where he insinuates that a <a href="https://www.coindesk.com/microscope-economic-environmental-costs-bitcoin-mining">Coindesk article</a> is the source. Yet, while his table is in the same style, there is no such table in that article. Nor, is there any source for the numbers for Gold mining, Governments, etc. WTF!?</p> <p>Why should I trust these Tweet Storms and Medium articles when they lack proper sources and do not have the reputability of a published study?</p> <h3>Sources</h3> <ul> <li><a href="https://www.tandfonline.com/doi/abs/10.1080/13563467.2019.1598964?journalCode=cnpe20">Is Green Growth Possible</a></li> <li><a href="https://www.sciencedirect.com/science/article/abs/pii/S2214629620302966?via%3Dihub">Bitcoin’s energy consumption is underestimated: A market dynamics approach</a></li> <li><a href="https://cbeci.org/">Cambridge Bitcoin Electricity Consumption Index</a></li> <li><a href="https://www.sciencedirect.com/science/article/pii/S254243511930087X">Renewable Energy Will Not Solve Bitcoin’s Sustainability Problem</a></li> <li><a href="https://www.researchgate.net/publication/317059599_2017_Global_Cryptocurrency_Benchmarking_Study">2017 Global Cryptocurrency Benchmarking Study</a></li> <li><a href="https://www.cell.com/joule/fulltext/S2542-4351(19)30255-7">The Carbon Footprint of Bitcoin</a></li> </ul> Some Keystone Xl Maths Adrian Unger Wed, 01 Apr 2020 00:00:00 -0700 https://staydecent.ca/blog/some-keystone-xl-maths https://staydecent.ca/blog/some-keystone-xl-maths <p>Alberta's United Conservative government recently announced they are investing $1.5 billion directly into the Keystone XL pipeline, plus a $6 billion loan guarantee. They must feel quite confident that oil prices will go back to historic highs?</p> <p>The loan guarantee means Alberta is on the hook for $6 billion, even if the project never completes. What's to prevent Saudi Arabia from starting another price war in the future? </p> <p>So, how many jobs will this create? 1,400 direct and 5,400 indirect jobs in Alberta during construction. Keystone XL is <a href="https://www.tcenergy.com/operations/oil-and-liquids/keystone-xl/">expected to be in service by 2023</a>, so, three whole years.</p> <div class="note">The <a href="https://www.tcenergy.com/operations/oil-and-liquids/keystone-xl/">Keystone XL website</a> mentions 2,800 jobs in Canada. The <a href="https://calgaryherald.com/opinion/varcoe-alberta-places-7b-bet-on-keystone-xl/wcm/57be4058-afdd-4af3-a7c1-bae243f9ef86/amp/">Calgary Herald</a> claims 2,600 jobs. I've chosen 7,000 to cover any indirect jobs the project <em>may</em> contribute to.</div> <p>So the UCP is putting up $6 billion dollars for ~7,000 jobs over three years. This project isn't without risk, so those jobs aren't a 100% guarantee.</p> <p>What if the UCP just paid 7,000 people a good salary? $100,000 seems like a good salary to me.</p> <pre><code><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">$</span><span style="color: #a9b7c6">6</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000&nbsp;</span><span style="color: #D6A856">/<br />&nbsp;&nbsp;&nbsp;$</span><span style="color: #a9b7c6">100</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">60</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000</span> </span> </code></code></pre> <p>Okay, so $6 billion could pay 60,000 people a salary of $100,000 for one year. But, the Keystone XL is going to create ~7,000 jobs for an incredible <em>three</em> years!</p> <pre><code><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">60</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000&nbsp;</span><span style="color: #D6A856">/&nbsp;</span><span style="color: #a9b7c6">3<br />&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">20</span><span style="color: #D6A856">,</span><span style="color: #a9b7c6">000</span> </span> </code></code></pre> <p>$6 billion could pay 20,000 people a salary of $100,000 for 3 years. To pay ~7,000 people a salary of $100,000, $6 billion would cover nearly a decade.</p> <p>What am I missing? Is my math wrong? It very well could be.</p> <p>I'm not saying we should just hand out $6 billion dollars to a fraction of the population. I'm just illustrating how little benefit there is in this project for such high risk.</p> <p>It seems even more ridiculous when Alberta's UCP just <a href="https://globalnews.ca/news/6759218/alberta-coronavirus-education-layoffs/">layed off 20,000 education workers</a>. Especially since we can <a href="https://databank.worldbank.org/reports.aspx?source=2&amp;series=SE.XPD.TOTL.GD.ZS&amp;country=">see</a> <a href="https://www.tandfonline.com/doi/abs/10.1080/09645292.2015.1059801?journalCode=cede20#.VcqUSJNViko">evidence</a> that education has economic benefits.</p> Why Redux over a more basic Global Store Adrian Unger Tue, 12 Nov 2019 00:00:00 -0800 https://staydecent.ca/code/why-redux-over-global-basic-store https://staydecent.ca/code/why-redux-over-global-basic-store <p>Lately there's been some &quot;<a href="https://twitter.com/thekitze/status/1191745686980694017">discussion</a>&quot; about the boilerplate around using Redux for application state. It's easy to look at Redux and think it's just an over-complicated global state. You could strip away much of the API and just implement an immutable object state, even mimicking the React state API of just <code>setState</code> and <code>getState</code>. </p> <div class="note">For a Global Store that supports <code>getState</code>, <code>setState</code> and Redux compatible actions and reducers, I created <a href="https://github.com/staydecent/atom" target="_blank">atom</a>.</div> <p>And, this will get you pretty far. Then, throw in a few helpers to map or select parts of the state object and use them as props in your Components, and you actually have a solution that's very friendly for rapid prototyping. Without the need to create specific Actions and Reducers, you reduce boilerplate, and can just start modifying state from your components:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">globalStore</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">setState</span><span style="color: #D6A856">({&nbsp;</span><span style="color: #a9b7c6">todos</span><span style="color: #D6A856">:&nbsp;</span><span style="color: #a9b7c6">globalState</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">todos</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">push</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">newTodo</span><span style="color: #D6A856">)&nbsp;})</span> </span> </code></code></pre> <p>When creating prototypes or MVPs, where speed is a priority, a simple global store is a good solution. So, why would you bother with the added complexity of Redux, Actions, and Reducers?</p> <h2>Traceable state changes</h2> <p>The origin of state change is easier to follow since the change is triggered by an Action. An action is basically just a descriptor of what should happen. ie. <code>ADD_TODO</code>, <code>UPDATE_TODO</code>, <code>REMOVE_TODO</code>. This becomes more important when you have Components at various points in your React tree that can change the same data in your store.</p> <p>You can also observe the order in which Actions were triggered and make sure the changes are happening in a sequence that makes sense for your app. This can be thought about in terms of data-integrity as well as the User Experience.</p> <p>With Redux Devtools, this is a really pleasant experience.</p> <h2>Refactoring</h2> <p>Because state changes are triggered by Actions, you can easily search your project for all instances of a specific Action being triggered. Perhaps, later on in the life of your project, you need to include some additional data for a specific type of state change. It's much easier to update a single Reducer to ensure that data now exists, and then search for all trigger instances for that Action.</p> <p>With a global <code>setState</code> solution, it's much harder to search for the triggers for a specific change to state, ie. </p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">setState</span><span style="color: #D6A856">({&nbsp;</span><span style="color: #a9b7c6">todos</span><span style="color: #D6A856">:&nbsp;</span><span style="color: #a9b7c6">todos</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">filter</span><span style="color: #D6A856">(({&nbsp;</span><span style="color: #a9b7c6">id&nbsp;</span><span style="color: #D6A856">})&nbsp;=&gt;&nbsp;</span><span style="color: #a9b7c6">id&nbsp;</span><span style="color: #D6A856">!==&nbsp;</span><span style="color: #a9b7c6">idToRemove</span><span style="color: #D6A856">)&nbsp;})</span> </span> </code></code></pre> <p>If you don't follow the exact formatting in every case where you remove a todo, you will not be able to perform a quick, project-wide search and replace.</p> <h2>Finding balance</h2> <p>The sentiment from that above embedded tweet isn't wrong. I've worked on several React/Redux projects where there were many dozens of files trying to group even more numerous action definitions, and reducers, and — oh my — middleware.</p> <p><strong>So how can you keep the number of Actions and Reducers in your project under control?</strong></p> <p>First, you need a generalized way to affect state change. <a href="https://github.com/staydecent/wasmuth/blob/master/packages/node_modules/%40wasmuth/path-reducer/path-reducer.js">Here's the <code>pathReducer</code></a> I use on every project.</p> <p>If a specific state change only occurs in one or two places (components) you should be fine to rely on the generalized state change. Once you have state changes that partially overlap, defining a specific action and reducer can help with any potential debugging (see above about Traceability).</p> <p>Then, once a project becomes more mature (re: Launched and with a userbase!), you may want to set time aside to write specific actions and reducers to replace those generalized state changes. Because of the improved traceability and refactoring, your project can become easier to maintain.</p> <h2>Anything else?</h2> <p>Did I miss anything? From my experience, the above two points are what make Redux and the concept of Actions and Reducers stand out.</p> <p>I still believe a simpler global <code>setState</code> can really help get an MVP out the door quickly. But, eventually, as an app and codebase grow, you'll likely benefit from the traceability and easy refactoring that comes with specific Actions and Reducers.</p> The Difference Between Static and Bound Methods Adrian Unger Tue, 08 Jan 2019 00:00:00 -0800 https://staydecent.ca/code/difference-between-static-and-bound-methods https://staydecent.ca/code/difference-between-static-and-bound-methods <p>Recently, at <a href="http://inputlogic.ca">work</a>, we were coming up with our <a href="https://github.com/inputlogic/styleguides/blob/master/react.md">React Style Guide</a> (based on <a href="https://github.com/airbnb/javascript/tree/master/react">AirBnBs</a>). One of the &quot;rules&quot; is to avoid binding methods within the render method (as this creates a new function each render), and a teammate mentioned, &quot;why not just use static arrow functions?&quot;</p> <p>While both solutions were practically equivalent, I worried about the technical differences. Static methods are defined on the Class <em>not</em> on each prototype instance. </p> <h2>Wait, so how is the arrow function properly binding the correct <code>this</code> to the static?!</h2> <p>This magic had me worried. So I pulled up a <a href="https://babeljs.io/repl">Babel REPL</a> and wrote two classes:</p> <pre><code class="language-jsx"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">class&nbsp;Static&nbsp;extends&nbsp;</span><span style="color: #a9b7c6">React</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">Component&nbsp;</span><span style="color: #D6A856">{<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">onClickDiv&nbsp;</span><span style="color: #D6A856">=&nbsp;()&nbsp;=&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;do&nbsp;stuff<br />&nbsp;&nbsp;</span><span style="color: #D6A856">}<br /><br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">render&nbsp;</span><span style="color: #D6A856">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&lt;</span><span style="color: #a9b7c6">div&nbsp;onClick</span><span style="color: #D6A856">={</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv</span><span style="color: #D6A856">}&nbsp;/&gt;<br />&nbsp;&nbsp;}<br />}<br /><br />class&nbsp;</span><span style="color: #a9b7c6">Bound&nbsp;</span><span style="color: #D6A856">extends&nbsp;</span><span style="color: #a9b7c6">React</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">Component&nbsp;</span><span style="color: #D6A856">{<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">constructor&nbsp;</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">props</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">super</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">props</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">bind</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">onClickDiv&nbsp;</span><span style="color: #D6A856">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;do&nbsp;stuff<br />&nbsp;&nbsp;</span><span style="color: #D6A856">}<br /><br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">render&nbsp;</span><span style="color: #D6A856">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&lt;</span><span style="color: #a9b7c6">div&nbsp;onClick</span><span style="color: #D6A856">={</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv</span><span style="color: #D6A856">}&nbsp;/&gt;<br />&nbsp;&nbsp;}<br />}</span> </span> </code></code></pre> <p>The transpiled Bound class was as you would expect, but the Static class resulted in: </p> <pre><code class="language-jsx"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">class&nbsp;Static&nbsp;extends&nbsp;</span><span style="color: #a9b7c6">React</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">Component&nbsp;</span><span style="color: #D6A856">{<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">constructor</span><span style="color: #D6A856">(...</span><span style="color: #a9b7c6">args</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;</span><span style="color: #a9b7c6">_temp</span><span style="color: #D6A856">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #a9b7c6">_temp&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">super</span><span style="color: #D6A856">(...</span><span style="color: #a9b7c6">args</span><span style="color: #D6A856">),&nbsp;</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv&nbsp;</span><span style="color: #D6A856">=&nbsp;()&nbsp;=&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;do&nbsp;stuff<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">},&nbsp;</span><span style="color: #a9b7c6">_temp</span><span style="color: #D6A856">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">render</span><span style="color: #D6A856">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #a9b7c6">React</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">createElement</span><span style="color: #D6A856">(</span><span style="color: #467B43">"div"</span><span style="color: #D6A856">,&nbsp;{&nbsp;</span><span style="color: #a9b7c6">onClick</span><span style="color: #D6A856">:&nbsp;</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">onClickDiv&nbsp;</span><span style="color: #D6A856">});<br />&nbsp;&nbsp;}<br />}</span> </span> </code></code></pre> <p>Oh! So maybe these are technically equivilant! But defining a Class method is still a different syntax than defining a function on a <code>this</code> reference. So I dropped the transpiled code into a <a href="https://developer.mozilla.org/en-US/docs/Tools/Scratchpad">FireFox scratchpad</a>.</p> <img src="/assets/media/class-prototypes.png" alt="Screenshot of the Firefox Console showing the Static and Bound prototypes." /> <p>The only difference seems to be a bound class method exists on the prototype whereas the static arrow function does not.</p> <p>But, how or why would this matter? In my experience, it usually doesn't, unless you want to mock a class method in your tests (by overriding the definition on the prototype), or — <a href="https://reactjs.org/docs/composition-vs-inheritance.html">god forbid!</a> — you plan on extending the class.</p> <p>In the end, because of the techincal difference, we aren't enforcing static methods over bound methods in our style guide, rather both are fine, as long as you're aware of the implications.</p> <p>Have I missed any other differences between the two? I'd love to know if there's other details to consider.</p> Debugging a Slow Rails App Adrian Unger Mon, 02 Jul 2018 00:00:00 -0700 https://staydecent.ca/code/debugging-a-slow-rails-app https://staydecent.ca/code/debugging-a-slow-rails-app <p>This past winter, I was tasked with figuring out why certain views on a Rails app were slowing to a crawl. While this was my first foray into Ruby/Rails debugging and performance tuning, I had decent experience with JavaScript and SQL query optimizing. </p> <p>Now, the notes I made are rough, and it's been about 6 months since the work was performed, so I may miss some details. But, I wanted to share my process in hopes of figuring out where and how I could improve.</p> <h2>Some project background</h2> <p>The app was actually 2 Rails apps: 1 for front-end and 1 for the API. The front-end Rails app had custom controllers/models that represented API resources. The API app was rather standard Rails API setup. </p> <p>The original developers were not available to discuss and walk through any code.</p> <p>And, the project was rather low-traffic, so this wasn't an issue at massive scale. This gave me hope the issue would be easier to spot :)</p> <h2>Inspecting the database</h2> <p>As this was a totally unfamiliar app to me, and the original developers were not around to help walk-through the code, I tried what would be the lowest amount of effort to improve performance: SQL query performance tuning!</p> <div class="note">I also should have prefixed this by saying, I'm really not that experienced in DevOps or SysAdmin tasks. I guess I'd call myself a Full Stack Developer, with a focus on Front-end.</div> <p>Luckily, for me, the app was hosted on Heroku and had a paid Heroku PostgreSQL database. Lucky, because you can simply click on the Database resource and then choose the &quot;Diagnose&quot; tab to inspect frequent and potentially slow queries. This will show you the SQL queries on the right and 2 graphs on the left. The graphs show <em>Number of Invocations</em> and <em>Average Time Per Invocation</em>. Here's a sample from a different app:</p> <img src="https://storage.googleapis.com/staydecent/blog/Screen%20Shot%202018-07-02%20at%2010.37.12%20AM.png" alt="Example Heroku PostgreSQL Diagnostics" /> <p>Short story: SQL did not appear to be the problem.</p> <h2>Inspecting Gems</h2> <p><a data-flickr-embed="true" href="https://www.flickr.com/photos/orbitaljoe/3338334900/" title="Gems"><img src="https://farm4.staticflickr.com/3540/3338334900_29c5e389b5_z.jpg" width="640" height="388" alt="Gems"></a><script async src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p> <p>My next plan was to inspect dependencies. This was a tactic I've picked up in tuning front-end JavaScript apps. Again, this is another potential low effort win. Basically, check the version of major libraries (including the runtime), and then check GitHub Issues or other bug tracking for those libraries for any issues raised about performance.</p> <p>The first thing I noticed was this project was using an old version of Ruby, which was nearing end of life for support. And, many versions since touted performance gains. I made note of this as a last resort. Really, I didn't think updating runtime would or should solve the problem by an acceptable magnitude. Sure, perhaps some of the Ruby language improvements would help this project, but I doubted (still do to this day) that it would have been significant enough to call it a day.</p> <h2>Enter Skylight</h2> <iframe src="https://giphy.com/embed/I0yKUIUewo0PC" width="480" height="480" frameBorder="0" class="giphy-embed" allowFullScreen></iframe> <p><a href="https://giphy.com/gifs/perfect-loops-eh-skylight-I0yKUIUewo0PC">via GIPHY</a></p> <p>After my generalized approaches failed to find anything significant, I moved on to a more specialized tool, <a href="https://www.skylight.io/">Skylight</a>. Skylight is a Ruby specific performance reporting service. And, thankfully, the client had Skylight enabled for a few weeks (IIRC they added it only after experiencing slow load times).</p> <p>Just like the Heroku monitoring graphs, Skylight identified the same views as being slow. Where the advantage came in, was Skylight also showed Ruby/Rails specific runtime details, matching response times to Controller methods, rather than just URL endpoints.</p> <p>Right away, I noticed something about &quot;Object Allocations&quot; and that they were through the freaking roof. This meant, Ruby was using wayyyy too much memory.</p> <h2>Narrowing in on the offending code</h2> <p>Skylight was nice enough to point me to the exact Controller method that was being called, which results in the massive amount of object allocations. But, it didn't tell me exact code (you know, like a line number!).</p> <p>So I went hunting for &quot;complex&quot; looking code. Meaning, some function or method that has loops, maybe too many references being created, that sort of thing. Nothing stood out. I inspected the classes that were being inherited, didn't see anything obvious.</p> <p>Okay, so I was closer to the source, but could not pinpoint it. I needed to profile the code locally.</p> <h2>Rack Mini Profiler</h2> <p><a href="https://github.com/MiniProfiler/rack-mini-profiler">rack-mini-profiler</a> [RMP] is rack middleware that displays a speed badge for every HTML page. Well, the first issue is I was inspecting the JSON API Rails app. But, it still had a HTML 404 page, yay!</p> <p>So, we can hit our API locally with some requests, RMP will do it's thing, and then I can manually load the 404 HTML page in a browser, which shows the previous requests via the RMP badge.</p> <p>Similar to what Skylight was showing me, I can clearly see a slow request stand out.</p> <p>I wanted to add some query string parameters to customize my mini-profiler usage. I Loaded up <a href="https://insomnia.rest/">Insomnia</a> for making HTTP requests to my local API server, hitting the endpoint that has been identified in the above steps.</p> <p>Following <a href="https://www.speedshop.co/2015/08/05/rack-mini-profiler-the-secret-weapon.html">this blog article</a> by Nate Berkopec, I figured the Garbage Collection feature was what I was after and added the <code>?pp=profile-gc</code> flag to my POST request.</p> <p>This Garbage Collection flag would track object allocations. So, I needed a baseline. I enabled the default Rails homepage and hit that:</p> <p><code>New objects: 3962</code></p> <p>Then, I made a request against the slow endpoint:</p> <p><code>New objects: 161271</code></p> <p>Yikes.</p> <p>But, still I have not yet been able to narrow down a chunk of code that is causing this excessive object allocation. I have only confirmed it in more detail.</p> <p>I then tried the <code>profile-memory</code> feature of RMP.</p> <pre><code><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">Total&nbsp;allocated</span><span style="color: #D6A856">:&nbsp;</span><span style="color: #a9b7c6">14772397&nbsp;bytes&nbsp;</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">162495&nbsp;objects</span><span style="color: #D6A856">)<br /></span><span style="color: #a9b7c6">Total&nbsp;retained</span><span style="color: #D6A856">:&nbsp;&nbsp;</span><span style="color: #a9b7c6">1647863&nbsp;bytes&nbsp;</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">12389&nbsp;objects</span><span style="color: #D6A856">)<br /><br /></span><span style="color: #a9b7c6">allocated&nbsp;memory&nbsp;by&nbsp;gem<br /></span><span style="color: #D6A856">-----------------------------------<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">5765128&nbsp;&nbsp;aws</span><span style="color: #D6A856">-</span><span style="color: #a9b7c6">sdk</span><span style="color: #D6A856">-</span><span style="color: #a9b7c6">v1</span><span style="color: #D6A856">-</span><span style="color: #a9b7c6">1.64.0<br />&nbsp;&nbsp;&nbsp;3202115&nbsp;&nbsp;activesupport</span><span style="color: #D6A856">-</span><span style="color: #a9b7c6">4.1.5<br />&nbsp;&nbsp;&nbsp;2962795&nbsp;&nbsp;activerecord</span><span style="color: #D6A856">-</span><span style="color: #a9b7c6">4.1.5<br />&nbsp;&nbsp;&nbsp;1764149&nbsp;&nbsp;2.1.3</span><span style="color: #D6A856">/</span><span style="color: #a9b7c6">lib<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">...</span> </span> </code></code></pre> <p>After double-checking the AWS library for performance issues or a new version with improvements. I moved down into the ActiveSupport and ActiveRecord libraries. These are part of Rails and are related to accessing your database. But, we knew at this point, that SQL wasn't an issue. The lead me to conclude the issue was something on the lines of</p> <blockquote> <p>Too much memory is being used when accessing data from the PostgreSQL database, causing the Ruby garbage collector to jump in, stressing the CPU and crashing the app.</p> </blockquote> <p>I eventually identified an Active Record method being used in a loop, <a href="https://apidock.com/rails/ActiveRecord/Base/serialize/class">serialize</a>. This view had quite a lot of records, and had nested Model records, and the way in which it was being serialized caused all the records' attributes to be initialized in memory.</p> <p>Unfortunately, I don't have access to the codebase anymore, and it's been ~6 months. But, from what I can recall, I ended up caching references for only the attributes that were needed by the front-end, instead of serializing all attributes of the records.</p> <p>I believe I made symbols for the attributes I wanted (which are only initialized once in Ruby, if I understand correctly).</p> <p>Then I reduced the amount of nested/related model data being serialized, again by reducing it to only what the front-end needed. As well as caching nested references. There were parent model instances that had arrays of children. Many of those children were shared across the parents. The original ActiveRecord code was re-initializing every single child instance, instead of re-using a potentially already initialized instance.</p> <p>In the end, this was enough to significantly reduce memory allocations, preventing the Ruby garbage collector from eating CPU, resulting in manageable response times.</p> <h2>The End</h2> <p>Anyway, that's the path I took. I had very little previous experience with Ruby/Rails prior to this. But, with the reporting that comes with Heroku and their PostgreSQL hosting, as well as Skylight and the rather awesome Rack Mini Profiler, the task was much less daunting.</p> <p>This isn't my area of expertize, but I certainly enjoy it. So if anyone has tips or advice, let me know!</p> Expired Kodak BWC Adrian Unger Sun, 18 Feb 2018 00:00:00 -0800 https://staydecent.ca/blog/expired-kodak-bwc https://staydecent.ca/blog/expired-kodak-bwc <p>I've been getting more and more into shooting 35mm film these past few months. So much so, that I'm starting to head out and only bring my film SLR, leaving my Sony NEX 6 behind.</p> <p>Recently, Angela found a bunch of rolls she bought maybe 15 years ago. I've now shot two of them, compensating for their expiration by dropping the ISO on the camera down a stop. For this roll of Kodak BWC, I could have stopped down another stop &endash; quite a few photos were underexposed.</p> <h3>Expired Kodak bwc (C41 process BNW) 200 shot at ISO 100</h3> <img src="/assets/media/Scan 0-2.jpg" alt="Expired Kodak bwc (C41 process BNW) 200 shot at ISO 100" /> <img src="/assets/media/Scan 1-2.jpg" alt="Expired Kodak bwc (C41 process BNW) 200 shot at ISO 100" /> <img src="/assets/media/Scan 2-2.jpg" alt="Expired Kodak bwc (C41 process BNW) 200 shot at ISO 100" /> <img src="/assets/media/Scan 4-2.jpg" alt="Expired Kodak bwc (C41 process BNW) 200 shot at ISO 100" /> <p>All shot on a Yashica FX-D, with a 28mm or 50mm lens.</p> <p>Apologies for the crummy scans. Working on that...</p> How To Keep API Calls Decoupled From React Components Adrian Unger Sun, 08 Oct 2017 00:00:00 -0700 https://staydecent.ca/code/how-to-keep-api-calls-decoupled-from-react-components https://staydecent.ca/code/how-to-keep-api-calls-decoupled-from-react-components <p>Keeping API calls decoupled from React components keeps your views pure and without side-effects! This makes it easier to test your views without having to worry about API calls. Your API and views can be tested separately.</p> <div class="note">I no longer agree with any of this! It was a nice thought experiment but, it's downfall is that Components become less encapsulated. I'd advocate that if you want to test a Component without worrying about API data, then break the Component in two: 1. Getting API data, and the child 2. Rendering some data. July 2, 2018</div> <h2>Some Assumptions</h2> <p>Before I dive any deeper, here are some assumptions: You are using React to render your views (HTML). You are using Redux, or something similar to handle state. Myself, I actually use Preact and Atom instead of React and Redux -- They are both smaller and their source codes are easier (for me) to understand, which I favour. That said, the APIs are basically the same. And, I'm also assuming you rely heavily on Redux/Atom and not on React's <code>setState</code> method.</p> <h2>Moving Request Logic Outside Of Your Views</h2> <p>If you're coming from MVC, then you know your views should be simple and without complex logic. Instead, you would use the Controller to load remote data and do any normalization. But where is the Controller when using React and Redux? There isn't <em>really</em> a controller, but that logic can be moved into <em>subscribers</em>.</p> <h3>What's a 'subscriber'?</h3> <p>With Redux (or Atom), your store reference has a <code>subscribe</code> method. See <a href="http://redux.js.org/docs/api/Store.html#subscribe">Redux docs</a> and <a href="https://github.com/staydecent/atom#subscribelistener">Atom</a>. I lack any experience with MobX, but it looks like you can get a similar result with just an Observable or a Spy, <a href="https://mobx.js.org/refguide/spy.html">see doc</a> (Anyone with more experience, please chime in!). <em>This</em> is where we can write our Controller-<em>esque</em> logic.</p> <h2>A Blog Example</h2> <p>So, let's say you have a blog page, and it loads a Parent or Page Component like <code>&lt;BlogPage ... /&gt;</code>, and you need to load some featured posts. Usually, this is where I would add a <code>componentDidMount</code> call to <code>BlogPage</code> and make an API request for some featured posts. But, like I said, this couples request logic with the view, which we don't want to do.</p> <p>Thankfully, we <a href="https://github.com/inputlogic/with-preact/blob/master/app/components/elements/link/actions.js">store the current URL</a> in our Atom store. If you don't, then you should!</p> <p>Now, <code>subscribe</code> is fired when any part of your state tree has changed. And, it does not tell you which part changed! So, we can use the following utility function to watch a specific path on our state tree and only invoke our callback if the value at that path has changed. (<em>Note: the next version of Atom will include this <code>watchStore</code> type API</em>)</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">import&nbsp;check&nbsp;from&nbsp;</span><span style="color: #467B43">'check-arg-types'<br /></span><span style="color: #a9b7c6">import&nbsp;pathOr&nbsp;from&nbsp;</span><span style="color: #467B43">'ramda/src/pathOr'<br /></span><span style="color: #a9b7c6">import&nbsp;merge&nbsp;from&nbsp;</span><span style="color: #467B43">'ramda/src/merge'<br /><br /></span><span style="color: #a9b7c6">import&nbsp;</span><span style="color: #D6A856">{</span><span style="color: #a9b7c6">subscribe</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">getState</span><span style="color: #D6A856">}&nbsp;</span><span style="color: #a9b7c6">from&nbsp;</span><span style="color: #467B43">'./store'&nbsp;</span><span style="color: #808080">//&nbsp;this&nbsp;is&nbsp;your&nbsp;local&nbsp;store&nbsp;file<br /><br /></span><span style="color: #D6A856">const&nbsp;</span><span style="color: #a9b7c6">toType&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">check</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">prototype</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">toType<br /><br /></span><span style="color: #808080">//&nbsp;Cache&nbsp;previous&nbsp;value&nbsp;for&nbsp;given&nbsp;path&nbsp;to&nbsp;allow&nbsp;easy&nbsp;diffing&nbsp;in&nbsp;the&nbsp;listener.<br /></span><span style="color: #D6A856">const&nbsp;</span><span style="color: #a9b7c6">cache&nbsp;</span><span style="color: #D6A856">=&nbsp;{}<br /><br /></span><span style="color: #808080">//&nbsp;Small&nbsp;wrapper&nbsp;around&nbsp;adding&nbsp;a&nbsp;subscriber&nbsp;to&nbsp;your&nbsp;store,&nbsp;that&nbsp;only&nbsp;calls&nbsp;the<br />//&nbsp;given&nbsp;cb&nbsp;if&nbsp;the&nbsp;value&nbsp;at&nbsp;the&nbsp;given&nbsp;path&nbsp;has&nbsp;changed&nbsp;since&nbsp;the&nbsp;last&nbsp;time<br />//&nbsp;the&nbsp;cb&nbsp;was&nbsp;invoked.<br /></span><span style="color: #a9b7c6">export&nbsp;</span><span style="color: #D6A856">default&nbsp;function&nbsp;</span><span style="color: #a9b7c6">watchStore&nbsp;</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">path</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">cb</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;const&nbsp;</span><span style="color: #a9b7c6">key&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">path</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">join</span><span style="color: #D6A856">(</span><span style="color: #467B43">','</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;const&nbsp;</span><span style="color: #a9b7c6">getPathVal&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">pathOr</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">undefined</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">path</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;const&nbsp;</span><span style="color: #a9b7c6">diff&nbsp;</span><span style="color: #D6A856">=&nbsp;()&nbsp;=&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #a9b7c6">newVal&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">getPathVal</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">getState</span><span style="color: #D6A856">())<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #a9b7c6">newVal&nbsp;</span><span style="color: #D6A856">===&nbsp;</span><span style="color: #a9b7c6">undefined</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;</span><span style="color: #a9b7c6">oldVal&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">cache</span><span style="color: #D6A856">[</span><span style="color: #a9b7c6">key</span><span style="color: #D6A856">]<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #a9b7c6">oldVal&nbsp;</span><span style="color: #D6A856">===&nbsp;</span><span style="color: #a9b7c6">undefined&nbsp;</span><span style="color: #D6A856">||&nbsp;</span><span style="color: #a9b7c6">oldVal&nbsp;</span><span style="color: #D6A856">!==&nbsp;</span><span style="color: #a9b7c6">newVal</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #a9b7c6">toType</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">newVal</span><span style="color: #D6A856">)&nbsp;===&nbsp;</span><span style="color: #467B43">'object'</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">cache</span><span style="color: #D6A856">[</span><span style="color: #a9b7c6">key</span><span style="color: #D6A856">]&nbsp;=&nbsp;</span><span style="color: #a9b7c6">merge</span><span style="color: #D6A856">({},&nbsp;</span><span style="color: #a9b7c6">newVal</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">cache</span><span style="color: #D6A856">[</span><span style="color: #a9b7c6">key</span><span style="color: #D6A856">]&nbsp;=&nbsp;</span><span style="color: #a9b7c6">newVal<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">cb</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">newVal</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">oldVal</span><span style="color: #D6A856">)<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;Let's&nbsp;invoke&nbsp;diff&nbsp;right&nbsp;away&nbsp;as&nbsp;we&nbsp;may&nbsp;want&nbsp;to&nbsp;react&nbsp;to<br />&nbsp;&nbsp;//&nbsp;our&nbsp;initialState&nbsp;set&nbsp;in&nbsp;our&nbsp;store.<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">diff</span><span style="color: #D6A856">()<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">subscribe</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">diff</span><span style="color: #D6A856">)<br />}</span> </span> </code></code></pre> <p>Ok, now we have the helpful wrapper around our store's <code>subscribe</code> method. It let's us target a specific path on our state tree, and only invoke our given callback function when the value at that path actually changes.</p> <p>Again, with the assumption that we keep the current URL up-to-date in our state tree, we can subscribe to changes like so:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">watchStore</span><span style="color: #D6A856">([</span><span style="color: #467B43">'url'</span><span style="color: #D6A856">],&nbsp;function&nbsp;</span><span style="color: #a9b7c6">loadData&nbsp;</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">url</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;switch&nbsp;(</span><span style="color: #a9b7c6">url</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #467B43">'/blog'</span><span style="color: #D6A856">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;Load&nbsp;blog&nbsp;posts&nbsp;from&nbsp;our&nbsp;API<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">loadBlogPosts</span><span style="color: #D6A856">().</span><span style="color: #a9b7c6">then</span><span style="color: #D6A856">(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break<br />&nbsp;&nbsp;}<br />})</span> </span> </code></code></pre> <p>I'm not going to cover the actual API request here. But, let's assume we get some array back from the API server and we're ready to store that in our state tree, we can fill in that <code>loadBlogPosts</code> promise callback with something like:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">import&nbsp;</span><span style="color: #D6A856">{</span><span style="color: #a9b7c6">set</span><span style="color: #D6A856">}&nbsp;</span><span style="color: #a9b7c6">from&nbsp;</span><span style="color: #467B43">'atom-lens-reducer'<br /></span><span style="color: #D6A856">...<br /></span><span style="color: #a9b7c6">loadBlogPosts</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">then</span><span style="color: #D6A856">((</span><span style="color: #a9b7c6">posts</span><span style="color: #D6A856">)&nbsp;=&gt;&nbsp;</span><span style="color: #a9b7c6">dispatch</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">set</span><span style="color: #D6A856">(</span><span style="color: #467B43">'blogPosts'</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">posts</span><span style="color: #D6A856">)))</span> </span> </code></code></pre> <p>Now when we update our state tree (and we already have a component connected to our Redux/Atom store) then we can pass that <code>blogPosts</code> value down to our <code>&lt;BlogPage posts={props.blogPosts} /&gt;</code> Component!</p> <h2>Another Example</h2> <p>Maybe your app as an API-backed autocomplete/type-ahead input field. You want to load and present results <em>as the user types</em>. Well, first you need to make sure you are storing your form values in your state tree. At this point, let's assume you are already syncing the input value of your autocomplete form in your Redux/Atom store.</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">&lt;</span><span style="color: #a9b7c6">Form&nbsp;name</span><span style="color: #D6A856">=</span><span style="color: #467B43">'globalSearch'</span><span style="color: #D6A856">&gt;<br />&nbsp;&nbsp;&lt;</span><span style="color: #a9b7c6">MySyncedInput<br />&nbsp;&nbsp;&nbsp;&nbsp;name</span><span style="color: #D6A856">=</span><span style="color: #467B43">'input'<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">...<br />&nbsp;&nbsp;/&gt;<br />&lt;/</span><span style="color: #a9b7c6">Form</span><span style="color: #D6A856">&gt;</span> </span> </code></code></pre> <p>And this input field is synced to your state tree as:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">{<br />&nbsp;&nbsp;</span><span style="color: #a9b7c6">forms</span><span style="color: #D6A856">:&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">globalSearch</span><span style="color: #D6A856">:&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">input</span><span style="color: #D6A856">:&nbsp;</span><span style="color: #467B43">'&lt;User&nbsp;Input&nbsp;Here!&gt;'<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">}<br />&nbsp;&nbsp;}<br />}</span> </span> </code></code></pre> <p>Then all we have to do is use that <code>watchStore</code> utility above to listen for when this input value changes and perform our API logic then:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">watchStore</span><span style="color: #D6A856">([</span><span style="color: #467B43">'forms'</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #467B43">'globalSearch'</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #467B43">'input'</span><span style="color: #D6A856">],&nbsp;(</span><span style="color: #a9b7c6">input</span><span style="color: #D6A856">)&nbsp;=&gt;&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;only&nbsp;perform&nbsp;request&nbsp;if&nbsp;input&nbsp;is&nbsp;3&nbsp;or&nbsp;more&nbsp;characters<br />&nbsp;&nbsp;</span><span style="color: #D6A856">if&nbsp;(</span><span style="color: #a9b7c6">input&nbsp;</span><span style="color: #D6A856">&amp;&amp;&nbsp;</span><span style="color: #a9b7c6">input</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">length&nbsp;</span><span style="color: #D6A856">&gt;&nbsp;</span><span style="color: #a9b7c6">2</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;Make&nbsp;API&nbsp;request<br />&nbsp;&nbsp;</span><span style="color: #D6A856">}<br />&nbsp;&nbsp;</span><span style="color: #808080">//&nbsp;You&nbsp;could&nbsp;also&nbsp;debounce&nbsp;or&nbsp;throttle&nbsp;this&nbsp;call&nbsp;to&nbsp;reduce&nbsp;hits&nbsp;on&nbsp;your&nbsp;API<br /></span><span style="color: #D6A856">})</span> </span> </code></code></pre> <p>No we don't have any of that logic in our hypothetical <code>&lt;GlobalSearchForm /&gt;</code> Component! It's just a simple function that accepts props and returns HTML! This should help with complexity by keeping your view (Components) simple, and your <em>&quot;Controller&quot;</em> logic separate. This makes writing tests much easier as you don't have to mock or intercept the API calls. Instead, you can directly pass in mocked API response data as props on a given Component.</p> <p>This is part of an evolving pattern of how I write React applications. I aim to write a document about the organization and libraries used. But, I felt this pattern (of keeping API calls separate from Components) was worthy of a more in-depth explanation -- I hope it helps reduce complexity in your React apps!</p> Where'd the Boardwalk Go? Adrian Unger Wed, 04 Oct 2017 00:00:00 -0700 https://staydecent.ca/blog/whered-the-boardwalk-go https://staydecent.ca/blog/whered-the-boardwalk-go <p>This past weekend we hiked  a similar route that we did about the same time last year. Only, we found one of our favourite sections had changed.</p> <p>Last year:</p> <img src="/assets/media/2016-02-06-13.20.56.jpg" alt="Forest Bathing Photo By Adrian Unger" /> <p>&nbsp;</p> <p>This year:</p> <img src="/assets/media/2017-01-29-12.25.11-1.jpg" /> So Long Cyanogen OS Adrian Unger Fri, 20 Jan 2017 00:00:00 -0800 https://staydecent.ca/blog/so-long-cyanogen-os https://staydecent.ca/blog/so-long-cyanogen-os <p>Almost exactly 2 years ago today, I bought a OnePlus One. It was (and is) my first real smartphone after spending $100 on the <a href="https://en.wikipedia.org/wiki/GeeksPhone_Peak" target="_blank">Geeksphone Peak</a>. And, I have next to no qualms with it. </p> <p>I don't know the specs off the top of my head, but it's more than capable for my needs. I watch videos, edit photos (even raw), read, and play Sodoku. I don't need it to be thinner, or lighter. The battery easily lasts a whole day. The screen and camera are good enough.</p> <p>Basically, it's a perfectly fine smartphone.</p> <p>The OS is also just peachy. My iOS experience is limited to the first (maybe 2nd?) iPad and the occasional use of my partners' iOS 10 device. In comparison to iOS, the main issue I had with Android was the app drawer and launcher. iOS was just so much nicer. Why would I want apps to appear in the drawer and on my home screen? Then, <a href="http://evie.com">Evie</a> came out. And it's the best.</p> <p>The Cyanogen OS flavour of Android was nice as well. It added some nice enough customizations, privacy and security features, and well... I'm not sure what else was unique to Cyanogen, or part of stock Android. Over-the-air updates <em>were </em>the best. They just happened, and never broke anything.</p> <p>Actually, I've only ever had one hiccup with my phone where the GPS stopped working. This happened after Pokemon Go came out &gt;:(. A factory reset, and everything's back to working.</p> <p>More recently, OTA updates did try to bundle some Microsoft apps with the updates... Then the updates stopped.</p> <p><a href="https://web.archive.org/web/20161225144318/https://www.cyanogenmod.org/blog/a-fork-in-the-road">CyanogenOS has shutdown.</a></p> <p>Well. That sucks.</p> <p>Now I need to find a new Android &quot;ROM&quot;. Hopefully one that has official builds for my OnePlus One (nicknamed &quot;Bacon&quot; apparently), and ideally also includes OTA updates. Though, it kind of feels like a complete gamble. I wonder how long I can wait, until I need to worry about security vulernabilities?</p> <p>Anyway, I guess this is goodbye.</p> Creating Reusable View Components for Android Adrian Unger Thu, 14 Jul 2016 00:00:00 -0700 https://staydecent.ca/code/reusable-android-view-components https://staydecent.ca/code/reusable-android-view-components <p>View components are all the rage in the frontend JavaScript world, with React popularizing their usage. Many <a href="https://docs.angularjs.org/guide/component">other frameworks</a> have added APIs to support this pattern as well. I've been pretty happy to adopt view components for web developement, so when I started learning Android, I quickly found myself wanting to breakdown my UI into components. </p> <p>Android/Java is full-OOP so it really just comes down to extending a built-in ViewGroup class and defining an XML layout.</p> <p>Here's an example of a stacked date view that could appear as a child of several different parent views. </p> <h2>First define the layout</h2> <pre><code class="language-xml"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">&lt;?</span><span style="color: #a9b7c6">xml&nbsp;version</span><span style="color: #D6A856">=</span><span style="color: #467B43">"1.0"&nbsp;</span><span style="color: #a9b7c6">encoding</span><span style="color: #D6A856">=</span><span style="color: #467B43">"utf-8"</span><span style="color: #a9b7c6">?&gt;<br /></span>&lt;merge&nbsp;xmlns:android="http://schemas.android.com/apk/res/android"<br />&nbsp;&nbsp;&nbsp;&nbsp;android:layout_width="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;android:layout_height="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&gt;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;TextView<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_width="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_height="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:text="Apr"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:textAllCaps="true"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&gt;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;TextView<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_width="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_height="wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_marginTop="-4dp"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:text="24"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:textSize="24sp"/&gt;<br /><br />&lt;/merge&gt;</span> </code></code></pre> <p>Simple enough. </p> <p>Note: the <code>&lt;merge&gt;</code> tag avoids redundant view groups within your layouts &mdash; check out the <a href="https://developer.android.com/training/improving-layouts/reusing-layouts.html#Merge">official docs</a> for more information. </p> <p>It's not apparent by just looking at the XML, but our component will be contained in a <code>LinearLayout</code>, that comes with our Java class.</p> <h2>Extend a view group</h2> <p>Create a new class that extends one of the built-in view groups. In this case, we'll extend the <code>LinearLayout</code>.</p> <pre><code class="language-java"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #808080">//&nbsp;imports&nbsp;have&nbsp;been&nbsp;left&nbsp;out<br /></span><span style="color: #D6A856">public&nbsp;class&nbsp;</span><span style="color: #a9b7c6">StackedDateView&nbsp;</span><span style="color: #D6A856">extends&nbsp;</span><span style="color: #a9b7c6">LinearLayout&nbsp;</span><span style="color: #D6A856">{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;</span><span style="color: #a9b7c6">TextView&nbsp;month</span><span style="color: #D6A856">;<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;</span><span style="color: #a9b7c6">TextView&nbsp;day</span><span style="color: #D6A856">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #a9b7c6">StackedDateView</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">Context&nbsp;context</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">AttributeSet&nbsp;attrs</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">super</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">context</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">attrs</span><span style="color: #D6A856">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">setOrientation</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">LinearLayout</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">VERTICAL</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">setGravity</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">Gravity</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">CENTER_HORIZONTAL</span><span style="color: #D6A856">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">LayoutInflater&nbsp;inflater&nbsp;</span><span style="color: #D6A856">=&nbsp;(</span><span style="color: #a9b7c6">LayoutInflater</span><span style="color: #D6A856">)&nbsp;</span><span style="color: #a9b7c6">context<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">getSystemService</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">Context</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">LAYOUT_INFLATER_SERVICE</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">inflater</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">inflate</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">R</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">layout</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">view_stacked_date</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">this</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">true</span><span style="color: #D6A856">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">month&nbsp;</span><span style="color: #D6A856">=&nbsp;(</span><span style="color: #a9b7c6">TextView</span><span style="color: #D6A856">)&nbsp;</span><span style="color: #a9b7c6">getChildAt</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">0</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">day&nbsp;</span><span style="color: #D6A856">=&nbsp;(</span><span style="color: #a9b7c6">TextView</span><span style="color: #D6A856">)&nbsp;</span><span style="color: #a9b7c6">getChildAt</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">1</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #a9b7c6">void&nbsp;setDate</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">Date&nbsp;date</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">SimpleDateFormat&nbsp;monthFormat&nbsp;</span><span style="color: #D6A856">=&nbsp;new&nbsp;</span><span style="color: #a9b7c6">SimpleDateFormat</span><span style="color: #D6A856">(</span><span style="color: #467B43">"MMM"</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">Locale</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">US</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">month</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">setText</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">monthFormat</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">format</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">date</span><span style="color: #D6A856">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">SimpleDateFormat&nbsp;dayFormat&nbsp;</span><span style="color: #D6A856">=&nbsp;new&nbsp;</span><span style="color: #a9b7c6">SimpleDateFormat</span><span style="color: #D6A856">(</span><span style="color: #467B43">"dd"</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">Locale</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">US</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">day</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">setText</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">dayFormat</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">format</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">date</span><span style="color: #D6A856">));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span> </span> </code></code></pre> <p>It's a super basic view component, but it still saves me from repeating code unnecessarily. All it takes to embed in one of your layouts is:</p> <pre><code class="language-xml"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #D6A856">&lt;</span><span style="color: #a9b7c6">com</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">yourdomain</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">app</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">StackedDateView<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android</span><span style="color: #D6A856">:</span><span style="color: #a9b7c6">id</span><span style="color: #D6A856">=</span><span style="color: #467B43">"@+id/stacked_date"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">android</span><span style="color: #D6A856">:</span><span style="color: #a9b7c6">layout_width</span><span style="color: #D6A856">=</span><span style="color: #467B43">"wrap_content"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">android</span><span style="color: #D6A856">:</span><span style="color: #a9b7c6">layout_height</span><span style="color: #D6A856">=</span><span style="color: #467B43">"wrap_content"&nbsp;</span><span style="color: #D6A856">/&gt;</span> </span> </code></code></pre> <p>And to populate the TextViews from your Java:</p> <pre><code class="language-java"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">StackedDateView&nbsp;stackedDate&nbsp;</span><span style="color: #D6A856">=&nbsp;(</span><span style="color: #a9b7c6">StackedDateView</span><span style="color: #D6A856">)&nbsp;</span><span style="color: #a9b7c6">root</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">findViewById</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">R</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">id</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">stacked_date</span><span style="color: #D6A856">);<br /></span><span style="color: #a9b7c6">stackedDate</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">setDate</span><span style="color: #D6A856">(</span><span style="color: #a9b7c6">someModel</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">getPublishedDate</span><span style="color: #D6A856">());</span> </span> </code></code></pre> <p>That's it.</p> AngularJS Separation of Concerns Adrian Unger Mon, 28 Sep 2015 00:00:00 -0700 https://staydecent.ca/code/angular-js-separation-of-concerns https://staydecent.ca/code/angular-js-separation-of-concerns <p>Recently, I was added to a couple of existing AngularJS projects to implement new features and refactor some existing ones. Specifically, the goal of refactoring was to move logic from places where it was not needed and to ensure everything was <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>.</p> <p>After reading through much of the official documentation and discussing with the original developers who started these projects, it was still not 100% clear how code should be separated and when each AngularJS concept should be used.</p> <p>Reading more developer blogs on the topic, the separation of concerns starts becoming more clear. But, to better understand each concept -- and to hopefully be able to succinctly convey to others -- I wanted to be able to explain the use for each AngularJS concept with a single terse sentence.</p> <p>Here is what I came up with:</p> <ul> <li>Directives should be used when you need to manipulate the DOM.</li> <li>Controllers define your 2-way databinding models.</li> <li>Services are for everything else ;) Rather, Services are for sharing domain logic and state.</li> </ul> <h3>Don't hesitate to create a new Service</h3> <p>The main issues I encountered when working on these existing AngularJS projects was reasoning about inheritance, the source of event triggers, and passing state between controllers. I found all of those issues could be solved by introducing a new Service and in some cases, expanding an existing one.</p> <p><code>$scope</code> should be explicit. Exposing an inhertited $scope method to your templates is not as easy to reason about than:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6">$scope</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">someFunc&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">MyService</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">sharedMethod</span><span style="color: #D6A856">;</span> </span> </code></code></pre> <p>Services can also be used to hold state instead of relying on various <code>emit</code> or <code>broadcast</code> events. And, again, is much easier to reason about that a property defined on <code>$rootScope</code>.</p> <p>If you have a Service that is the single source of truth for some state object, you do not need to worry about inheriting some <code>$rootScope</code> property or parent controller property.</p> <p>Regarding MVC, Services are not limited to defining Models to persist data and hold the most up-to-date reference of that data. You can also have services for representing volatile state, file uploads, API wrappers etc.</p> <p>Having plenty of focused, moderately sized Services is definitely better than having fat Controllers.</p> <p>Anyway, my AngularJS experience is limited but this has been my takeaway so far. Here are some articles that helped form these views:</p> <ul> <li><a href="http://onehungrymind.com/angularjs-sticky-notes-pt-1-architecture/">AngularJS Sticky Notes Pt 1 – Architecture</a></li> <li><a href="http://toddmotto.com/rethinking-angular-js-controllers/">Rethinking AngularJS Controllers</a></li> <li><a href="https://github.com/johnpapa/angular-styleguide">AngularJS Style Guide</a></li> </ul> Authenticating LoopBack AngularJS SDK Routes Adrian Unger Wed, 12 Aug 2015 00:00:00 -0700 https://staydecent.ca/code/authenticating-loopback-angular-sdk-routes https://staydecent.ca/code/authenticating-loopback-angular-sdk-routes <p>I am currently working on writing an API backend with <a href="http://loopback.io/">LoopBack</a>. This API is a rewrite of an older Python codebase which has an AngularJS client. While the backend needs improving the current AngularJS client is holding up just fine.</p> <p><a href="http://expressjs.com/">ExpressJS</a> was the front-runner since the whole team has experience with it.But, when I came across LoopBack, which is a framework built on top of ExpressJS for quickly creating dynamic REST APIs, it seemed like a perfect fit. Not only do you get the time saving JSON based API generation, but also the <a href="https://docs.strongloop.com/display/public/LB/AngularJS+JavaScript+SDK">LoopBack AngularJS SDK</a>.</p> <p>The AngularJS SDK will auto-generate AngularJS services for accessing your models and remote methods on the server. It's basically an ORM for your RESTful API endpoints. And, you can always keep it up-to-date by re-running the CLI tool or by using the Grunt build plugin.</p> <p>Taking the <a href="https://docs.strongloop.com/display/public/LB/Create+AngularJS+client#CreateAngularJSclient-Services">example code</a> for an authentication service you can see how easy it is to use the generated <code>lb-services</code> for accessing your API endpoints. After calling <code>login</code> the generated services will also handle passing the access token for subsequent calls to your resources.</p> <h3>But, what I could not find in the documentation was how to manage an active user session on the client.</h3> <p>Following the <a href="https://github.com/strongloop/loopback-example-angular/blob/master/client/js/app.js#L4">LoopBack AngularJS Example</a> I was using <code>angular-ui-router</code>. Without a clear example of authenticating routes with LoopBack and AngularJS I instead looked for a general example for <code>angular-ui-router</code>.</p> <p>I found this great article by Jorge Silva: <a href="http://blog.thejsj.com/angular-js-authentication-with-ui-router/">Angular.js Authentication with UI-Router</a>. This succinctly covers requiring a logged in user for specific angular.ui routes. Which is great, since I am new to Angular and angular-ui-router.</p> <p>Wait! If the <code>lb-services</code> are handling passing the access token for each subsequent call, they must be storing that data somewhere!</p> <p>Indeed. Inspecting my generated <code>lb-services</code> source, I found a <code>LoopBackAuth</code> service that would load the <code>localStorage</code> values onto itself. Easy enough. In your custom <a href="https://docs.strongloop.com/display/public/LB/Create+AngularJS+client#CreateAngularJSclient-Services">authentication service</a> you can inject the <code>LoopBackAuth</code> service and write a simple helper:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #808080">//&nbsp;client/js/services/auth.js<br /></span><span style="color: #D6A856">function&nbsp;</span><span style="color: #a9b7c6">isLoggedIn</span><span style="color: #D6A856">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #a9b7c6">LoopBackAuth</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">currentUserId&nbsp;</span><span style="color: #D6A856">&amp;&amp;&nbsp;</span><span style="color: #a9b7c6">LoopBackAuth</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">accessTokenId</span><span style="color: #D6A856">;<br />}</span> </span> </code></code></pre> <p>Then, the <code>authenticated</code> promise <a href="http://blog.thejsj.com/angular-js-authentication-with-ui-router/">outlined by Jorge Silva</a> can be adapted:</p> <pre><code class="language-javascript"><code><span style="color: #EAD8E2"> <span style="color: #a9b7c6"></span><span style="color: #808080">//&nbsp;client/js/site.js<br /></span><span style="color: #D6A856">var&nbsp;</span><span style="color: #a9b7c6">authenticated&nbsp;</span><span style="color: #D6A856">=&nbsp;[</span><span style="color: #467B43">'$q'</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #467B43">'AuthService'</span><span style="color: #D6A856">,&nbsp;function&nbsp;(</span><span style="color: #a9b7c6">$q</span><span style="color: #D6A856">,&nbsp;</span><span style="color: #a9b7c6">AuthService</span><span style="color: #D6A856">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;</span><span style="color: #a9b7c6">dfd&nbsp;</span><span style="color: #D6A856">=&nbsp;</span><span style="color: #a9b7c6">$q</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">defer</span><span style="color: #D6A856">();<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: #a9b7c6">AuthService</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">isLoggedIn</span><span style="color: #D6A856">())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">dfd</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">resolve</span><span style="color: #D6A856">();<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #a9b7c6">dfd</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">reject</span><span style="color: #D6A856">(</span><span style="color: #467B43">'Not&nbsp;logged&nbsp;in.'</span><span style="color: #D6A856">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #a9b7c6">dfd</span><span style="color: #D6A856">.</span><span style="color: #a9b7c6">promise</span><span style="color: #D6A856">;<br />&nbsp;}];</span> </span> </code></code></pre> <p>Well, that's working for now. I am quite new to Angular and actually have yet to read any of the official documentation. So ... I could be way off on this one ;)</p> Thoughts On React And Mithril Adrian Unger Thu, 28 May 2015 00:00:00 -0700 https://staydecent.ca/code/thoughts-on-react-and-mithril https://staydecent.ca/code/thoughts-on-react-and-mithril <p>I've been using Facebook's React for most new UI components in recent months at Ecquire. And, only more recently, using Mithril.</p> <p>They are both awesome for one very simple reason: No templates. Especially with how small I break out my UI components. I don't like having a file with 3 lines of HTML with Mustaches thrown in.</p> <p>Both, Mithril and React, use Virtual DOMs to avoid the need for separate template files. Other than that, they really are not that similar.</p> <p>Lately, I have been enjoying rigidness over flexibility in my coding. I have found it forces specific functionality over generalizing. Which I have found easier to test and maintain. Because of this, I am biased towards choosing Mithril instead of React.</p> <p>React is quite flexible. It has about twice as many API methods as Mithril. This is necessary since React rather you not reference the DOM directly. Instead, you rely on Lifecycle Methods, which inform on the state of the DOM and when to perform operations at the <em>correct time</em>.</p> <p>Mithril is not flexible. You render a Virtual DOM and you assign event handlers. Mithril offers a few nice methods for common patterns (HTTP Requests, Promises, Getter-Setters etc.).</p> <p>If you were to migrate React components to Mithril, your main entry point for converting React's Lifecycle methods is the non-HTML-standard attribute called config: <em>&quot;This special parameter allows you to call methods on the DOM element after it gets created.&quot;</em></p> <p>If you process data that should affect the UI/DOM you need to rely on Mithril's built-in helpers, or you will have to <a href="https://lhorie.github.io/mithril/mithril.computation.html" target="_blank">manually tell Mithril to compute changes</a>. Because Mithril does less to abstract away how it computes changes and renders a Virtual DOM you are forced to learn a bit more of the Mithril source and how it actually works.</p> <p>Good thing the source is tiny. About 5kb gzipped. This is a stark contrast to React. The logic is really not that hard to follow, and stack traces (in my anecdotal experience) were tiny and easy to follow compared with monstrous and dense with React.</p> <p>There are pros and cons to either. For me, debugging and maintenance are the worst part of programming and with Mithril I was able to reduce friction for both.</p> GMOs Are Neither Good Nor Bad Adrian Unger Sat, 02 May 2015 00:00:00 -0700 https://staydecent.ca/blog/gmos-are-neither-good-nor-bad https://staydecent.ca/blog/gmos-are-neither-good-nor-bad <p>I came across <a href="http://www.nytimes.com/2015/04/25/opinion/sunday/how-i-got-converted-to-gmo-food.html">How I Got Converted to GMOs</a> via <a href="http://ma.tt/2015/05/more-on-gmos">ma.tt</a>. This is a response to that article. </p> <p>I think it’s wrong to assume this is black and white or that the issue of GMOs is the centre of feeding the world. There are actual issues threatening how we feed everyone going forward. The UN has pretty much got <a href="http://www.unep.org/wed/2013/quickfacts/">it</a> <a href="http://www.un.org/en/events/desertificationday/background.shtml">covered</a>. But agriculture is not the same the world over, issues in America may not translate to Brazil. </p> <p>I think we all need to be honest and not conflate the issues that differ around the world with each other. So, looking at America, many questions can be asked:</p> <ul> <li>How many GMO crops are even grown for human consumption?</li> <li>How many monocultures exist to feed cows? For ethanol? For tobacco? For alchohol?</li> <li>Why is 30% of all food grown, wasted? (Jones, 2004 cited in Lundqvist et al., 2008)</li> <li>How can we control pest issues?</li> <li>How can we have crops adapt with climate change?</li> <li>How can we prevent (even reverse) soil degradation?</li> <li>How can we prevent (even reverse) nitrogen run-off?</li> </ul> <p>My point is, instead of trying to determine if A) GMOs are good, or B) GMOs are bad, we should instead be looking at actual issues of agriculture. GMOs may end up being part of the problem, or part of the solution but on either side, GMOs will not be the sole culprit. </p> <p>Converting crops to GMOs does not address all of the issues I mentioned above. And neither does converting all GM crops to non-GM. </p> <p>This conversation is a waste of time when it comes to actually fixing issues of agriculture. Specific to GMOs, sure, let’s talk about labeling which is a social/political issue. Or, let’s talk about the <a href="http://nassimtaleb.org/tag/precautionary-principle/">precautionary principle</a> which has specific implications with GMOs. </p> <p>But there is way too much variability in the usage of GMOs to argue, at a global scale, that GMOs are good or bad. For instance, having a GM eggplant benefit a farmer in Bangladesh does not give a pass to GM rapeseed in Europe. Those are two separate cases with their own implications.</p> <blockquote> <p>Oilseed rape can be described as a high-risk crop for crop-to-crop gene flow and from crop to wild relatives.</p> </blockquote> <p>(From Genetically modified organisms (GMOs): The significance of gene flow through pollen transfer) </p> <p>That issue of cross-pollination and biodiversity is specific to GM rapeseed and does not conclude much in terms of eggplants in Bangladesh. </p> <p>I think we need to stop arguing GMOs and start addressing the actual problems facing agriculture around the world. There is and will continue to be a wide array of causes to those problems and probably even more solutions to consider.</p> Roy Choi On Tradition Adrian Unger Wed, 22 Oct 2014 00:00:00 -0700 https://staydecent.ca/blog/roy-choi-on-tradition https://staydecent.ca/blog/roy-choi-on-tradition <p>Roy Choi is a pioneer of awesome street food with the Kogi, korean taco, truck.</p> <blockquote> <p>nothing is authentic and tradition is in the human mind. we can create new ones as long as we are honest. I think it's more important to challenge authenticity and tradition than accepting them if they are old and irrelevant. </p> </blockquote> How We Work Remotely At Ecquire Adrian Unger Tue, 14 Oct 2014 00:00:00 -0700 https://staydecent.ca/blog/how-we-work-remotely-at-ecquire https://staydecent.ca/blog/how-we-work-remotely-at-ecquire <p>This is how Ecquire caught my attention ~2 years ago. Then, just a couple weeks after joining, I got to meet the team at <a title="Nerds on vacation" href="http://staydecent.ca/blog/nerds-on-vacation">Nerds on Vacation</a> in Tofino, BC. Which was awesome.</p> My First East Coast Fall Adrian Unger Mon, 06 Oct 2014 00:00:00 -0700 https://staydecent.ca/photos/my-first-east-coast-fall https://staydecent.ca/photos/my-first-east-coast-fall <img class="aligncenter wp-image-291 size-large" src="http://i.imgur.com/9oYn3Bz.jpg" alt="Processed with VSCOcam with n3 preset" /> <p>Still not used to being on the east coast but I am starting to appreciate the more subtle beauty.</p> Veganism Adrian Unger Mon, 31 Mar 2014 00:00:00 -0700 https://staydecent.ca/blog/veganism https://staydecent.ca/blog/veganism <p class="big">Veganism is not the end-all answer to a better world. <a href="http://leobabauta.com/">Leo Babauta</a> is <a href="http://zenhabits.net/vegan/" target="_blank">claiming that is is</a>. To me, Leo is still reacting. He is presenting Veganism as the only answer to numerous injustices. And yet, closing his eyes to other perspectives.</p> <p>I'd like to highlight that Veganism does not take in account all injustices and can potentially perpetuate some.</p> <p><strong>Agriculture is complex</strong></p> <p>Food, one of life's staples, has been left in the hands of the few. This results in large, industrial, mono-cultures to make up for the quantity needed to feed the world. Moreover, <a href="http://www.unep.org/wed/2013/quickfacts/" target="_blank">nearly one-third of all food produced is needlessly wasted</a>. This falsifies the apparent need to increase production and convert more acreage into industrial farming practices.</p> <p>Agriculture is one of the leaders in emissions and other pollutants. Considering just food waste, the global carbon footprint is <a href="http://www.rtcc.org/2013/09/11/un-global-food-waste-emissions-greater-than-us-transport-sector/" target="_blank">twice that from the US transport sector</a>.</p> <p>The majority of Almonds and soft-fruit trees in California require bees to be trucked in from around the country. Because these almond farms are so large, there is no natural habitat for bees to live year-round. One Washington-based company is responsible for <a href="http://modernfarmer.com/2013/05/bee-convoy-shipping-interstate-apiaries/" target="_blank">shipping 3.2 million bees each year.</a> Should Vegans give up Almonds?</p> <p>Declining bee populations are <a href="http://e360.yale.edu/feature/declining_bee_populations_pose_a_threat_to_global_agriculture/2645/" target="_blank">threatening global agriculture</a>. But, to many vegans, <a href="http://vegetus.org/honey/honey.htm" target="_blank">Honey is exploitation of bees</a>. So, how do we incentivize increasing bee populations if collecting and selling honey is unethical? Should we expect our already stressed food system and workers to take care of bee populations without increasing profit and wages?</p> <p>Overall, Veganism doesn't take into account sustainability. Not eating animals does not mean a more sustainable farming system as external inputs such as blood meal (often byproducts of the industrial animal system) and synthetic nitrogen fertilizers (mainly, petroleum based) are required to be brought into the farming system. There are different ways to close to loop, and allow food-producers to not rely on external inputs. One rather successful system is <a href="https://www.biodynamics.com/biodynamics.html" target="_blank">Biodynamic Farming</a>, which often uses manure based fertilizers (produced on-site).</p> <p>I guess my point is, Veganism is not an end. You can be vegan and support monocultures, food waste and land degradation. Which could <a href="http://www.rtcc.org/2013/09/15/un-targets-global-land-degradation-deal-in-2015/" target="_blank">lead to imperilling millions of human lives</a>.</p> <p><strong>Human well-being is often ignored</strong></p> <p>The majority of manual labour performed on farms is by migrant or temporary workers. <a href="http://www.migrantclinician.org/issues/migrant-info/migrant.html" target="_blank">In the US</a>, &quot;migrant farmworkers still suffer mortality and morbidity rates greater than the vast majority of the American population, due in part to the combination of poverty, limited access to health care, and hazardous working conditions. Farmwork is listed as the second most dangerous occupation in the United States behind mining.&quot;</p> <p><a href="http://www.justicia4migrantworkers.org/saw_new.htm" target="_blank">In Canada</a>, &quot;The Canadian government insists that foreign agricultural workers are treated the same as Canadian workers but nothing can be further from the truth.&quot;</p> <p>Eating Vegan does not directly address the issue of human well-being.</p> <p><strong>Veganism is not the only answer</strong></p> <p>I am not attacking Veganism. I am attacking the view that non-Vegans need to be called out. There are so many shitty situations in our world. We can't expect everyone to rank each injustice in the world the same. I agree we all have a duty to educate, but <strong>never</strong> to inscribe how one should react to that knowledge.</p> Falling Water Adrian Unger Tue, 25 Feb 2014 00:00:00 -0800 https://staydecent.ca/photos/falling-water https://staydecent.ca/photos/falling-water <img class="aligncenter size-full wp-image-178" src="http://i.imgur.com/oLVnW36.jpg" alt="falling-water" /> Burnaby Lake Adrian Unger Sat, 22 Feb 2014 00:00:00 -0800 https://staydecent.ca/photos/burnaby-lake https://staydecent.ca/photos/burnaby-lake <img class="size-full wp-image-172" src="http://i.imgur.com/mPs7Kov.jpg" alt="Burnaby lake" /> <img class="size-full wp-image-173" src="http://i.imgur.com/MTOh3bj.jpg" alt="Burnaby lake" /> Sointula Adrian Unger Mon, 13 Jan 2014 00:00:00 -0800 https://staydecent.ca/photos/sointula https://staydecent.ca/photos/sointula <p class="big">My partner and I have been scouring British Columbia, checking out potential properties to purchase. While the truth of BC's high cost of land may have hit hard, the excuse to venture into previously looked-over corners of this truly beautiful province has been a thrill.</p> <p>More recently, we jumped on a ferry from Horseshoe Bay and hit the road nearing the northern end of Vancouver Island. From there, another ferry took us to Malcolm Island, home of Sointula – a Finnish founded, yet failed, utopia.</p> <img class="alignnone size-sd-full-image wp-image-47" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-10.19-940x625.jpg" alt="2013-12-07 10.19" width="940" height="625" /> <p>The property we were checking out was a bust for us – but we quickly rebounded with the joy of exploring this fishing village.</p> <img class="alignleft size-sd-half-image wp-image-50" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-12.01.36-470x470.jpg" alt="2013-12-07 12.01.36" width="470" height="470" /><img class="alignright size-sd-half-image wp-image-49" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-11.57.42-470x470.jpg" alt="2013-12-07 11.57.42" width="470" height="470" /><img class="alignnone size-sd-full-image wp-image-48" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-11.57.19-940x625.jpg" alt="2013-12-07 11.57.19" width="940" height="625" /> <p>Impressed by the south-western views towards Vancouver Island, we headed to see the eastern view over the Queen Charlotte strait. Before we even got the other other coast, we were aghast by Salal bushes, taller then ourselves!</p> <img class="alignnone size-sd-full-image wp-image-56" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-15.51.42-940x625.jpg" alt="2013-12-07 15.51.42" width="940" height="625" /><img class="alignleft size-sd-half-image wp-image-55" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-15.45.39-470x470.jpg" alt="2013-12-07 15.45.39" width="470" height="470" /><img class="alignright size-sd-half-image wp-image-63" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-08-12.32.59-470x470.jpg" alt="2013-12-08 12.32.59" width="470" height="470" /> <p>The forest opened up to one of the most spectacular views I will likely ever have the privilege to enjoy. Zero clouds and just as the sun was setting we looked over the Queen Charlotte Straight towards the Coastal Mountains.</p> <img class="alignnone size-sd-full-image wp-image-58" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-16.03.43-940x625.jpg" alt="2013-12-07 16.03.43" width="940" height="625" /> <img class="alignnone size-sd-full-image wp-image-60" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-16.08.36-940x625.jpg" alt="2013-12-07 16.08.36" width="940" height="625" /> <img class="alignnone size-sd-full-image wp-image-61" src="http://staydecent.ca/wp-content/uploads/2014/01/2013-12-07-16.12.25-940x625.jpg" alt="2013-12-07 16.12.25" width="940" height="625" /> <p>A fine spot to attempt a utopia.</p> A birthday story from the 135 Adrian Unger Tue, 17 Dec 2013 00:00:00 -0800 https://staydecent.ca/blog/a-birthday-story-from-the-135 https://staydecent.ca/blog/a-birthday-story-from-the-135 <p class="big">Awhile back, I lived atop Burnaby Mountain. Often, I would take the 135 bus in and out of downtown Vancouver. One of these times, returning from downtown, I happened to sit next to a fellow who wished to share a story.</p> <p>The man overtly smelled of alcohol.</p> <p>Not sensing any danger, there was no reason for me not to hold a conversation. Though, the light banter quickly took a turn as he mentioned that it was his birthday and he's off to see his father for the first time in years.</p> <p>Trying to not get too personal, nor trigger any sour reaction, I politely reply &quot;I hope everything goes well with your dad.&quot; Perhaps sensing my timidness, he quickly acknowledges his sent and demeanour, &quot;My birthday is not a good day, I try to celebrate, but the memories are awful.&quot; Again, timidly I reply, &quot;it's good you're staying positive.&quot;</p> <p>&quot;When I was a kid my mom overdosed on my birthday.&quot;</p> <p>I tried not to react. With overbearing solemn, I looked him in the eyes and nodded. Trying to avoid words altogether I utter, &quot;that's tough.&quot;</p> <p>He goes through the details. How he remembers lights, sirens, police, his mom. He stays away from drugs because of it. But, openly admitting, &quot;I struggle as an alcoholic.&quot;</p> <p>His stop is up. I acknowledge his openness and wish him, with as much conviction as I can, a happy birthday.</p> The Value of a Web Developer Adrian Unger Fri, 26 Jul 2013 00:00:00 -0700 https://staydecent.ca/blog/value-of-a-web-developer https://staydecent.ca/blog/value-of-a-web-developer <p class="big">James Somers asks if coders are worth it. Well, I’d like to answer that.</p> <p>I may have missed the point of <a href="http://www.aeonmagazine.com/living-together/james-somers-web-developer-money/">the article</a>, but he seems to be drawing attention to web developers making <em>good</em> money while working for web startups, which aren’t serious business. Serious, in the sense that the problems being solved aren’t grand or meaningful enough.</p> <blockquote> <p>A lot of the stuff going on just isn’t very ambitious.</p> </blockquote> <p>Some web developers work on problems that fail, or don’t evoke passion. But their work shouldn’t affect the value of all web developers, or current salary trends. Well, unless you want it to.</p> <h2>A short story</h2> <p>A couple of years ago I had an empty feeling from the low valuation of the work I did. I <em>felt</em> I had this practical skill – which by the way, I did sit in the basement of my moms house to foster – where I was paid good money (especially for a community-college dropout) to do some stuff for people or businesses that I did not gain satisfaction from. Which left only the monetary gains as the measurement of value of what I was doing.</p> <p>So I did something about it. I reached a point as a freelancer that I could start turning down work. And instead of evaluating potential work based on the monetary gains, I started seeking out companies that were doing something big—something that I could garner some passion for.</p> <p>And, we’re not all passionate about the same things. So we can’t really evaluate the whole industry of web developers without knowing what each person is passionate about.</p> <h2>What are you passionate about?</h2> <p>For me, I have a few passions, though they all potentially stem from the same source. But, what’s interesting (for this blog post at least) is that web development is not one of them. For me, web development is a practical skill — one that I enjoy immensely and still do as an unpaid hobby outside of my job, but not a passion.</p> <p>I needed to satisfy my empty feeling. And that’s what I set out to do. I picked clients and industries more aligned to my passions. James Somers (at least the one portrayed in the article), could do the same. He could take his practical skill as a web developer and apply it to businesses and clients in the writing/publishing industry. It’s not a perfect solution, but things take time, and incremental improvements should not be overlooked.</p> <p>As skilled web developers, you decide your own worth. Measure it how you want, just remember—like much of life—money isn’t everything.</p> Living and Working From a Trailer Adrian Unger Tue, 12 Feb 2013 00:00:00 -0800 https://staydecent.ca/blog/living-working-from-a-trailer https://staydecent.ca/blog/living-working-from-a-trailer <p class="big">Last year, I spent 8 months living and working out of a 5th Wheeler. I did this with my partner, on a public farm, in the city of Vancouver. What were we thinking?!</p> <p>When the oppurtunity presented itself, we knew we had to take it. After moving every year for the past 5 years, ending up in a basement suite we couldn't afford, and growing ever more sick of <em>city life</em> the choice was clear. At least in retrospect.</p> <h2>A Unique Oppurtunity</h2> <p>Soon after taking a job at the <a href="http://ubcfarm.ca">UBC Farm</a>, my partner came across another oppurtinty there: being a caretaker. After some deliberation, we jumped on it, moving onto the farm and into the trailer in February of 2012. </p> <p>The farm has two caretaker couples, each in their own trailer. We purchased our trailer from the caretakers we were replacing. Caretaking, for those curious, means looking after buildings, irrigation, chickens, gates and locks.</p> <p>But, this ain't no trailer park, nor the side of the road. The farm provides city hookups for water, sewer, electricty and we even had access to Univercity WiFi. Even better, we had our own private growing space. And a pretty substantial front-yard.</p> <img src="http://i.imgur.com/Hm5tpla.jpg" alt="Our front-yard at the UBC Farm" title="Our front-yard at the UBC Farm" /> <h2>Trailer Life</h2> <p>Again, take into account, this is <em>Trailer Life</em> on some of the most beautiful land in Vancouver. But, basically, this is how it breaks down:</p> <ul> <li>You feel like a giant for the first few days.</li> <li>Leaks are pretty much your biggest concern.</li> <li>Do your dishes! (otherwise there's no room to cook).</li> <li>Don't forget to empty the poop-tank!</li> <li>Only one person can be doing a <em>standing</em> activity.</li> <li>His and Her sinks?! Yeah right, morning routines are done in succession.</li> <li>Did I mention do you dishes? Oh, and tidy anything else, otherwise you have no surfaces.</li> </ul> <img src="http://i.imgur.com/cwNHubk.jpg" alt="Tiny Apartment" title="The inside of our 5th-wheeler" /> <p>Everything about living in a trailer (with city hookups) is just the same as living in an apartment. A tiny, tiny apartment.</p> <h2>Working in the Trailer</h2> <p>Honestly, there isn't anything interesting to say about this. The desk was a bit small. Sometimes I felt cornered in. But the view was absolutely fantastic. <em>I work well with a good view.</em></p> <img src="http://i.imgur.com/QSTzPHh.jpg" alt="Trailer Workspace" title="Sometimes I sit, sometimes I stand" /> <h2>Looking back</h2> <p>We are lucky to have had such a unique living oppurtunity. Living in nature (even if the farm was a <em>popular</em> public place) within such close proximity to the city, was the perfect situation for us. And, the forced simplicity (re: downsizing) was liberating. I've always wanted my posssesions to be focused, and when two people share a closest (that doubles as storage and knive holder), you have no choice.</p> <img src="http://i.imgur.com/DkgMiWY.jpg" alt="Our garden at UBC Farm" title="Our garden at its peak, even the weeds" /> <p>Even now, <a href="http://vivaoaxaca2013.wordpress.com">sitting in Mexico</a> evaluating our next steps, I've realised how much that space to grow food meant to both of us. Though, we can't afford our farm yet, we know that we want <em>some</em> land of some size. And that's going to dictate or next location.</p> <p><em>View all photos on <a href="http://imgur.com/a/TZn1Y">Imgur</a></em></p> Freelance Rumination Adrian Unger Mon, 17 Dec 2012 00:00:00 -0800 https://staydecent.ca/blog/freelance-rumination https://staydecent.ca/blog/freelance-rumination <p class="big">I've been out of the freelance game since I joined Ecquire back in May. And, I feel I need to reflect on those years freelancing and see if I learned anything.</p> <p>I think it's better that I'm writing this 8 months after leaving the freelance business – there are a tonne of articles that get into the nitty-gritty details of freelancing – this way, I can offer a broad overview. And, since significant time has passed, whatever lessons I remember will <em>scientifically</em> be more important!</p> <h2>Communication</h2> <p>When anyone asks my advice regarding freelancing, this is it: Communicate. Often. effectively. And, be polite.</p> <p>A good portion of your clients won't know a thing about the web design (nor development) process. They may even try to fit their knowledge of their industry or domain onto you. So, you'll have to communicate. Every single step. And you'll need to be able to explain your decisions, obiously.</p> <p>Most of my clients were located in different parts of the world. And, besides the couple Skype calls I would have during the life of a project, all communication was via Email. When it comes to email, <em>brevity is best</em>. if your client wants more details, they'll ask. </p> <blockquote> <p>Hey John, I'm working on getting the Contact Page designed. Can we talk about the Gallery page closer to Friday?</p> <p>The infinte scrolling is taking longer than hoped, I'll let you know tomorrow where it's at.</p> <p>I'm going to start developing all of the page designs. I'm aiming to have the initial versions up next week. I'll update you this Friday on my progress.</p> </blockquote> <h2>Charge more</h2> <p>Ha. How young and stupid I was. Everytime I raised my rates (sometimes by 100%), I was met with acceptance. I've never lost a project from a high-rate. I've come down to a lower rate before, but still didn't lose the project. I clearly should have had higher rates much sooner than I did.</p> <h3>When should I raise my rates?</h3> <p>If you're ever turning down work, because you're too busy. Double your rate. If they turn you down, oh well, you're too busy anyway. If they're fine with it, you've got a hellish couple weeks coming up, but you just doubled your rate!</p> <h3>The thing about hourly rates</h3> <p>They don't reflect the value you provide. Yeah, I can go in and fix that crappy jQuery or WordPress plugin in under an hour. Is the value I'm providing worth my hourly rate? No.</p> <p>Think like a consultant. You aren't selling 3 hours of code-monkeying nor 2 days of design-monkeying! You are selling yourself (O boy) as a product. You have experience, opinions and knowledge that informs the code you spit out each hour. You are oncall to answer and educate your client on the work being done, and the problems being solved.</p> <h2>I guess that's it</h2> <p>Five years of freelancing. All I learned was I should charge more and that communicating effectively and often is key. <em>Whew</em>.</p> Well-Functioning Ecosystems Adrian Unger Sat, 06 Oct 2012 00:00:00 -0700 https://staydecent.ca/blog/well-functioning-ecosystems https://staydecent.ca/blog/well-functioning-ecosystems <p class="big">John Lius, a documentary film-maker and ecologist, has dedicated his life spreading the knowledge and successes of rehabilitating large-scale, damaged ecosystems.</p> <p><a href="http://youtu.be/J3WisjXYik4">Watch the Green Gold Documentary</a> by John Lius on YouTube. Spoilers below.</p> <p>The results of the projects covered in the above documentary are astounding. People in Jordan, China, Ethiopia and elsewhere have turned baron, dry, desert-like landscapes back into lush, hydrated, functioning ecosystems. These rejuvenated lands, bring back native species of plants (and even leopards in the case of Ethiopia), as well as open the door to growing foods to <em>sustain</em> local communities.</p> <p>Interesting, as many of these baron lands were, at some point, fertile and used for agriculture. But, through unsustainable practices &mdash; mainly mismanaged water and over-grazing by livestock &mdash; these lands were devastated.</p> <p>John Lius' documentary contains a wealth of information, but I'd like to highlight three points. (if you don't like spoilers, watch the documentary first!)</p> <h2>First, Learn from the past mistakes of Agriculture</h2> <p>Like always, we can learn much from the past. Look at places like Jordan, Ethiopia and China. In each of these places, humans have lived for thousands of years. We can directly see the impact of poor agricultural practices on the land. And, how it negatively affects communities today.</p> <h2>Second, Desertified lands can be brought back to life</h2> <p>Hearing about droughts, pollution, starvation etc. one can feel hopeless. Have hope! John Lius has documented, what has been in my opinion, the most profound success humans have achieved in regards to ecosystems: <strong>Desertified lands can be brought back to lush, fertile, food-bearing, functioning ecosystems!</strong> If this does not astound you. Just repeat it in your head for a few hours.</p> <p>Even more astounding, the proven technique does not require modern agricultural technologies! So succinctly summarized by Ta Fuyuan:</p> <blockquote> <p>The objective was to give the hills a 'hat' on top, a 'belt' in the middle and 'shoes' at the bottom. The trees planted on top of the hill form the hat; The terraces form the belt; And, constructed dams at the bottom of the hills form the shoes.</p> </blockquote> <p>Once the hat, belt and shoes are in place, the once baron lands become fertile. The Hat, Belt &amp; Shoes trap rain, improving the hydrology. This prevents mudslides and loss of rainwater, and increases the ability to sustain food for local communities, presently and for future generations.</p> <h2>Third, Economies should be based on well-functioning Ecosystems</h2> <p>Finally, I can coherently explain why Canada's current economic stability makes me uncomfortable. Canada's economy, like many others, puts monetary value on the goods and services that <em>rely</em> on ecosystems. If an ecosystem shows signs of degradation or instability, this does not immediately affect the economies based on it. Only, once you reach a breaking point, and things collapse, do the economies reflect the reality of the failing ecological systems. At which point, rectifying the situation is magnitudes more difficult.</p> <p>John makes the argument that economies should be based <em>directly</em> on the ecosystems that feed the goods and services. This way, ecosystems could not be exploited (and depleted) for short but large monetary gains. Instead, economies would rely on <em>well-functioning ecosystems</em>, and would experience a more real-time association with them.</p> <p>Well, something to ponder at least.</p> Should We Care About Organic Adrian Unger Fri, 21 Sep 2012 00:00:00 -0700 https://staydecent.ca/blog/should-we-care-about-organic https://staydecent.ca/blog/should-we-care-about-organic <p class="big">Anna Bronnes recently <a href="http://ecosalon.com/foodie-underground-addressing-the-organic-myth/" target="_blank">published on Ecosalon</a> a link-bait article&mdash;with good intentions&mdash;that unfortunately fell a bit flat.</p> <p>I entirely agree with the intention:</p> <blockquote> <p>In the modern age, if you are able to comfortably put food on the table, it is inexcusable to not think about what you are eating.</p> </blockquote> <p>But, the article lacks significant information to help those wishing to become more informed about the food system. It also, subtly, suggests devaluing what &quot;Organic&quot; labels actually represent.</p> <h2>Thinking About What You're Eating</h2> <p>Anna Brones brings up a good point that personal health is not the only reason to consider Organic&mdash;or to question your food in general:</p> <blockquote> <p>Food cannot be reduced to single elements. It’s not just about antioxidants or carbohydrates or omega 3s. Food is a process, a compilation of nutrition, environment and experience.</p> </blockquote> <p>So, what is it about? What should people be aware of? What are the impacts of food production, and how can I as a consumer influence those impacts? The issues surrounding producing and consuming food can be pretty comfortably categorized into the following (I'm ignoring health for now):</p> <ol> <li><strong>Social</strong> <em>How are the workers treated?</em></li> <li><strong>Environmental</strong> <em>Can the environment sustain the current production, and for how long?</em></li> <li><strong>Ethical</strong> <em>How are the Livestock treated?</em></li> <li><strong>Economical</strong> <em>How is the increased price distributed?</em></li> </ol> <p>But, if you're unaware of current negative issues surrounding food production, then it's easy to give each of those questions the benefit of the doubt. But, with <a href="http://www.justicia4migrantworkers.org/bc/">mistreated migrant workers</a> in British Columbia, monocultures and their <a href="https://www.agronomy.org/publications/aj/abstracts/92/5/938">negative long-term yield variability</a>, Synthetic Nitrogen Fertilizers <a href="https://www.agronomy.org/publications/jeq/abstracts/38/6/2295">actually depleting soil nitrogen levels</a> and how <a href="http://ageconsearch.umn.edu/bitstream/124892/2/Wang.pdf">rising energy costs affects food costs (PDF)</a>, there are plenty of issues to be concerned about.</p> <h2>Some Thoughts on Organic</h2> <p>I'm sure Anna means no harm, but when she says &quot;Slap the big O on anything and you’re sure to attract a certain demographic.&quot; Her tone and and adjective devalue the significance of Organic, and what small-to-medium farmers endure to gain that status. In Canada and the US, <a href="http://canadagazette.gc.ca/rp-pr/p2/2009/2009-06-24/html/sor-dors176-eng.html">gaining Organic Certification</a> is no simple matter, nor is it <a href="http://www.ccof.org/fees.php">cheap</a>. We, should respect that the Farmers' are being more thoughtful of how they choose to produce.</p> <p>Organic, is not a perfect indicator of a <em>good</em> product, but it is a highly controlled word, with many positive attributes associated with it. And, when you do reach that point when Organic is <em>not</em> a good enough indicator for <em>good</em> food you can look into bio-dynamic farming, permaculture, Fairtrade, Community-Support Agriculture etc.</p> <p>Really, there is just <em>so</em> much to learn when it comes to producing and consuming food! And, Anna is right:</p> <blockquote> <p>If we are going to move the food system forward, in a progressive and sustainable manner, we have to be asking the hard questions, and that takes more than just reading a headline.</p> </blockquote> <p>In response to: <a href="http://ecosalon.com/foodie-underground-addressing-the-organic-myth/" target="_blank"><a href="http://ecosalon.com/foodie-underground-addressing-the-organic-myth/">http://ecosalon.com/foodie-underground-addressing-the-organic-myth/</a></a></p> Browser Testing as a Chrome Extension Adrian Unger Tue, 28 Aug 2012 00:00:00 -0700 https://staydecent.ca/code/browser-testing-jasmine-chrome-extension https://staydecent.ca/code/browser-testing-jasmine-chrome-extension <p class="big">Running Jasmine tests against a webpage? Forget headless-browser testing. Why not inject your tests right into the actual web page?</p> <p>At <a href="//ecquire.com">Ecquire</a>, we integrate with a bunch of services to move your data where it needs to be. Testing our code, to assert that we can properly identify data from different websites (Gmail, LinkedIn, Twitter, Facebook etc.), is something we'd like to do easily and frequently.</p> <p>I spent a day researching (re: playing) with different JavaScript testing libraries and Headless Browsers. I ended up trying <a href="zombie.labnotes.org">Zombie.js</a> and <a href="casperjs.org">Casper.js</a> (ontop of <a href="phantomjs.org">Phantom.js</a>). I found Zombie to be the most pleasant, mainly because of it's documentation&mdash;it's organized as a linear storyline of a zombie attack! </p> <p>Sigh, but headless browsers were a dead-end, as our code needs to run on pages only accesible after logging in (I found captcha's hard to automate against) and JavaScript wasn't being executed as expected. </p> <p><strong>Duh!</strong></p> <p><em>Ecquire is a chrome extension</em>. Webkit based headless-browsers would render <em>close</em> at best. Oh, right. And we already have a Jasmine Test suite in a Chrome Extension (though, those ones didn't inject themselves into the active tab).</p> <h2>Cool, let's inject some tests!</h2> <p>The following will assume you are familiar with <a href="http://pivotal.github.com/jasmine/">Jasmine</a> and JavaScript in general. If anything is unclear, let me know, and I'll try to clarify.</p> <p>The biggest barrier for this to work, was the <em title="the output of our test results">reporting</em>. I didn't want to spend much more time on this, so I did some <a href="//duckduckgo.com">DDGing</a> and found this awesome <a href="https://github.com/larrymyers/jasmine-reporters">Console Reporter</a>.</p> <div class="note">Note: turns out Jasmine comes with its own Console Reporter inspired by Larry Myers. I prefer Larry's output style, so I stuck with it.</div> <p>Great. The unfamiliar territory is taken care of. Now, to write the Chrome Extension code that actually runs the Jasmine specs inside an active tab, outputting the test results to console!</p> <h3>The Chrome Extension</h3> <p>I wrote a boilerplate Chrome Extension, for <a href="https://github.com/staydecent/jasmine-chrome-extension">Browser Testing with Jasmine</a>. Here's an explanation of what it does:</p> <h4>1. Whitelist some domains, where we want our tests to run. For Ecquire, that meant mail.google.com, twitter.com, etc.</h4> <p>Google is cracking down on security when it comes the Chrome Web Store. Which means we have to whitelist <em>everything</em> in our <dfn title="Every chrome extension needs one, it declares unique attributes about the app or extension.">manifest.json</dfn> file. Since our test extension won't be public-facing, we can be overly zealous in our whitelisting:</p> <pre><code>"permissions": [ "https://*/", "http://*/", "tabs" ],</code></pre> <h4>2. Declare some <a href="https://code.google.com/chrome/extensions/content_scripts.html">content scripts</a> that will be executed within active tabs on those domains.</h4> <p>In <em>manifest.json</em> again:</p> <pre><code>"content_scripts" : [ { "matches" : [ // Again, overly zealous in our whitelisting ;) "http://*/*", "https://*/*" ], "js" : [ // The JS libraries we want available in an active tab "jasmine/lib/jasmine.js", "jasmine/lib/jasmine.console_reporter.js", "plugins/jquery-1.7.2.min.js", "myapp/some_dir/code_that_needs_testing.js" ], "run_at" : "document_idle", "all_frames" : false } ],</code></pre> <h4>3. Check if we're on a good domain, to show our <a href="http://code.google.com/chrome/extensions/pageAction.html">page action</a> button</h4> <p>First up, we'll need to declare a script file to run in the background, in <em>manifest.json</em>:</p> <pre><code>"background": { "scripts": ["background.js"] },</code></pre> <p>In <em>background.js</em> we'll listen for any changes to the URL of any tab.</p> <pre><code>chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if (tab.url.indexOf('google') &gt; -1) { // ... show the page action. chrome.pageAction.show(tabId); } });</code></pre> <h4>4. When are page action is clicked, run some Jasmine specs!</h4> <p>We'll also need an event listener for when the page action is clicked. Check out the full <a href="https://github.com/staydecent/jasmine-chrome-extension/blob/master/background.js">background.js</a> file to see that (it's the same idea as jQuery click events). When clicked, we'll inject our Jasmine specs and run them via Chrome's Extension APIs:</p> <pre><code>// load our spec file chrome.tabs.executeScript(tab.id, { file: 'my_spec_file.js' }, function() { // once loaded, run jasmine chrome.tabs.executeScript(thisTab.id, { file: 'path_to/JasmineSpecRunner.js' }); });</code></pre> <p><em>That's it!</em></p> <p>With this, you can now test your JavaScript against <em>real</em> webpages, and actually see the output. It's not as automated as using headless browsers, but it's pretty much 1-click. And, I'm guessing the same idea can be brought to Safari and FireFox extensions.</p> <p>Though the use-case for this is pretty specific to Ecquire, I thought it was pretty neat&mdash;and worth sharing. Would love to hear any reactions or thoughts on this!</p> Nerds on Vacation Adrian Unger Fri, 20 Jul 2012 00:00:00 -0700 https://staydecent.ca/blog/nerds-on-vacation https://staydecent.ca/blog/nerds-on-vacation <p class="big">I spent 10 days this July, in the breathtaking town of <a href="https://en.wikipedia.org/wiki/Tofino%2C_British_Columbia">Tofino</a>, surfing and writing code as part of <a href="//ecquire.com/nov" target="_blank">Nerds on Vacation</a>.</p> <p>It was an entirely positive experience, filled with practical lessons for startups, people who work from laptops, and remote teams. My teammate <a href="http://talsraviv.com">Tal</a> wrote about <a href="http://talsraviv.com/2012/07/18/the-nerds-on-vacation-effect/">The Nerds on Vacation Effect</a>, which basically describes the huge boost in productivity, even when surfing almost every day.</p> <h2>Increased Productivity</h2> <p><a href="//talsraviv.com">Tal</a> talks a bit about the <em>why</em> behind The Nerds on Vacation Effect. And, I agree with him. Being totally relaxed in an idyllic setting allowed me to push out 6 hours worth of code in 4. Well, I can't prove that. But, it certainly felt as though I was accomplishing more in less time. Maybe seeing the <a href="http://www.flickr.com/photos/staydecent/7600163866/in/photostream">beautiful weather from our &quot;office&quot;</a> and checking the <a href="http://www.surf-forecast.com/breaks/Tofino/forecasts/latest/six_day">surf report</a> in the morning was enough to push me to work more efficiently.</p> <p>In any case, I'm hoping to test this effect a few more times. Maybe it won't be surfing, but some other idyllic setting like being close to hiking, biking, yoga or a nice knitting chair. Whatever takes 100% focus away from work.</p> <h2>Remote teams</h2> <p>There's lots of <a href="http://news.ycombinator.com/item?id=460693">talk</a> around about if <a href="http://dt.deviantart.com/journal/We-re-all-remote-220038037">remote teams</a> work or not. I'm most definitely a proponent. I don't like cities, buildings or concrete. Even though I love technology and building for the web, I much prefer being near nature and in small towns. And, I think there are plenty of <a href="http://37signals.com/svn/posts/3064-stop-whining-and-start-hiring-remote-workers">successful companies</a> out there, proving remote works. </p> <p>For a remote team to <em>actually</em> work, I think they need stronger ties than a team sharing office space. The <em>culture</em> needs to be strong and present for every team member. And, those people, though living in different areas of the world, need to be able to get along when they all get together and share a house for a couple weeks!</p> <p>If you're running a remote team, I highly recommend you take a look at getting those Nerds on Vacation! Once, twice or four times a year. Whatever, just get some facetime. </p> <h2>Laptops == Lifestyle</h2> <p>Being able to work from a Laptop is a fact that I am immensly grateful for. Most of the world is now connected via WiFi, even <a href="http://bosquevillage.com/en/">off-the-grid huts</a>. Being a part of a remote team means I get to work and live in a trailer on a <a href="//ubcfarm.ca">farm</a>, join the team in Tofino to work and surf, and eventually I'll try being a <a href="//digitalnomad.com">Digital Nomad</a>.</p> Comparing Responsive Image Proposals Adrian Unger Fri, 11 May 2012 00:00:00 -0700 https://staydecent.ca/code/comparing-responsive-image-proposals https://staydecent.ca/code/comparing-responsive-image-proposals <p class="big">Responsive Web Design has gained in usage and ease of use. But one, rather large, missing piece is responsive images.</p> <p>The <a href="http://www.w3.org/community/respimg/">W3 Responsive Images Community Group</a> and <a href="http://www.whatwg.org/">WHATWG</a> have been coming up with some ideas.</p> <p>I should preface this post as such: I very well may have a lack of understanding or even misunderstanding regarding HTML spec proposals. Also, If you're not aware of <a href="http://www.alistapart.com/articles/responsive-web-design/">Responsive Web Design</a>, this post won't be very interesting.</p> <h2>Two Proposals</h2> <p>As it stands there are two (popular) proposals for responsive images:</p> <pre><code>&lt;img src="face-600-200@1.jpeg" alt="" set="face-600-200@1.jpeg 600w 200h 1x, face-600-200@2.jpeg 600w 200h 2x, face-icon.png 200w 200h"&gt;</code></pre> <p>And:</p> <pre><code>&lt;picture alt=""&gt; &lt;source src="mobile.jpg" /&gt; &lt;source src="large.jpg" media="min-width: 600px" /&gt; &lt;source src="large_1.5x-res.jpg" media="min-width: 600px, min-device-pixel-ratio: 1.5" /&gt; &lt;img src="mobile.jpg" /&gt; &lt;/picture&gt;</code></pre> <p>With many voicing their preference for the latter. Mainly because:</p> <ul> <li>It's easier to read</li> <li>It's familiar (see the <code>&lt;video&gt;</code> and <code>&lt;source&gt;</code> tags)</li> </ul> <p>And, I agree. But, <a href="https://twitter.com/#!/zcorpan">Simon Pieters</a> brings up some points on the <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2012-May/035784.html">complexity of implementation</a>. In brief, the <code>srcset</code> attribute is easier to implement in the spec, and would avoid some pitfalls that the <code>&lt;picture&gt;</code> element would create for JavaScript developers. Read the above link for details.</p> <h2>Pick one</h2> <p>So, besides smaller semantic grievances, the main argument for each proposal is: </p> <ul> <li><code>&lt;picture&gt;</code> is easier to read and write as a developer</li> <li>The <code>srcset</code> attribute is easier to implement and would have less pitfalls for JavaScript developers</li> </ul> <p>This is no easy decision. And, in getting a little more familiar with the community discussions regarding new HTML specs, I have gained much respect for those involved.</p> <p>In the end, I still feel the <code>&lt;picture&gt;</code> element fits better along the existing HTML spec and elements. If <code>srcset</code> were to be implemented it would really be crossing a new boundary in terms of power given to an attribute&mdash;which I don't currently support. <code>&lt;picture&gt;</code> would take longer to implement, and JavaScript developers would have to be wary of creating bugs. But, I think friendly and familiar syntax outweighs both of those issues.</p> jQuery Multiline Text Input Adrian Unger Fri, 20 Apr 2012 00:00:00 -0700 https://staydecent.ca/code/jquery-multiline-text-input https://staydecent.ca/code/jquery-multiline-text-input <p class="big">A jQuery plugin that replaces a textarea with multiple text inputs, automatically appending a new input when the last is filled with content.</p> <p>I created this plugin as part of a provisionary coding task for an unnamed startup. The idea is to simplify server-side processing while having more control of the user input&mdash;And, hopefully, a better experience for the user. </p> <img src="http://i.imgur.com/ZBxbt.png" alt="Screenshot of a similar implementation by Google" title="Inspired by Google Profiles" /> <h2>The Concept</h2> <p>Instead of asking a user to enter each item (Ex. Places lived) on a new line or comma separating them within a textarea, each item is entered in an individual text input. But, we want to allow an indefinite amount of items and asking the user to click a button (to add another input) would be annoying. So, the plugin intelligently appends an empty text input as soon as the user starts typing the last input.</p> <p><em>But, how do you know how many inputs need to be processed on the server-side?</em></p> <p>Good question! This is handled by the plugin on the client-side; the plugin combines all of the single line inputs back into a single textarea, with each item on a newline, before submitting the data.</p> <h2>Demonstration</h2> <p>Select the &quot;Result&quot; tab in the below JSFiddle frame to test-drive a basic example.</p> <iframe style="width: 100%; height: 380px" src="http://jsfiddle.net/dQSNP/5/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe> <h2>Usage</h2> <p><code>$('textarea.multiline').multilineText();</code></p> <p>Check out the <a href="https://github.com/staydecent/jQuery-MultilineText">GitHub Repo</a> for more information and to grab the code.</p> The Essence of Blogging Adrian Unger Fri, 23 Mar 2012 00:00:00 -0700 https://staydecent.ca/code/essence-of-blogging https://staydecent.ca/code/essence-of-blogging <p class="big">Inspired by Dustin Curtis' <a href="http://svbtle.com/">Svbtle</a> and the subsequent open-source project <a href="https://github.com/NateW/obtvse">Obtvse</a>, I took a shot at simplifying the blogging interface.</p> <p>Actually, even before Dustin <a href="http://dcurt.is/codename-svbtle">unveiled</a> the interface for Svbtle, the concept had inspired me&mdash;with the three words <em>essence of blogging</em> I began to think about what that meant to me. I took it to mean two types of posts, those which are ones purely written word, and those that are commentary on some link. The main difference being that the latter would have its' title link to the external source.</p> <p>So, I started dreaming up an interface that began with a single text field.</p> <h2>A demo of sorts</h2> <p>To catch the wave of this <a href="http://news.ycombinator.com/item?id=3744237">fiasco</a>, I tested out that interface concept today. So, the demo is limited to only the writing interface, though it can save the post data to <em>localStorage</em>.</p> <p>View the demo <a href="http://test.staydecent.webfactional.com/Gumblog/" target="_blank">here</a>.</p> <h3>Some notes:</h3> <ul> <li>I've only tested it on Chrome.</li> <li>Try pressing 'tab' or 'enter' ;)</li> <li>Try pasting a URL</li> <li>'DRAFT' and 'PUBLIC' do nothing</li> <li>type <code>clearPost()</code> in console to clear localStorage data</li> </ul> <h2>A bit of an explanation</h2> <p>Like I said, the goal is to accommodate two types of posts, purely written word, and <em>link posts</em>. The type of post is determined based on what you enter in the initial field (which is actually the title field). If a URL, we'll fetch the title from that page, and populate the title field with it (moving the URL to the link field). If the initial field is just text, we wait until you press <em>enter</em> or <em>tab</em> and generate a <em>local</em> permalink for the post.</p> <p>In both cases, once the initial field is dealt with, we move the focus to the body field.</p> <h2>A note about the name</h2> <p>You may notice that the Demo comes with the title <em>Gumblog</em>. It will eventually be working blog software, made purely to allow me to experiment with PHP 5.4, <a href="http://pjax.heroku.com/">PJAX</a> and this interface concept. You can view the base framework, Gum, <a href="https://github.com/staydecent/Gum">here</a>.</p> <p>I would love to hear your thoughts about this interface concept. Feel free to reach out via email or Twitter.</p> Moving Off App Engine Adrian Unger Fri, 24 Feb 2012 00:00:00 -0800 https://staydecent.ca/code/moving-off-app-engine https://staydecent.ca/code/moving-off-app-engine <p class="big">Google App Engine provided a slew of learning, and allowed me to rapidly build my side-projects. But, it's time to move on.</p> <p>Google App Engine was exciting, and gave me an easy to run environment to learn Python. I built my portfolio and blog on GAE, as well as the original <a href="http://fullioapp.com">Fullio App</a> and the current <a href="http://cookitlocal.com">Cook It Local</a>. But, each of those projects, for their own reasons, has outgrown (or no longer feels at home) on Google App Engine. Let's go over the migration of each project!</p> <h2>Staydecent.ca</h2> <p>The GAE version of my website is pretty awesome. It's flexible, fast and allows me to update everything <a href="http://www.staydecent.ca/bits/publishing-by-email-app-engine">by email</a>. But, I also have a few static mini-sites for clients, fun projects and tests that I like to keep under the staydecent.ca domain. Uploading a folder of HTML and CSS isn't so simple on GAE compared to Apache. I also want to have my entire site backed up with Git. After finding <a href="https://github.com/mojombo/jekyll">Jekyll</a> inflexible (at least with my lack of Ruby knowledge) I spent a day building a <a href="https://github.com/staydecent/staydecent.ca">ridiculous <em>build</em> script</a> for a static website. It seems to be working&mdash;you're looking at it!</p> <h2>Fullio App</h2> <p>This was the most painful. Trying to get this idea out fast, while battling with actual client work, I hit a major roadblock with GAE. Fullio processes emails with large, full-sized image file attachments and uploads them to Amazon S3. GAE has (had?) a limit that prevented me from sending requests larger than 10 mb to S3. This just would not fly, as I wanted to allow people to host their mega-images. Failing to get Flask or Django (or Python for that matter) running smoothly on my Windows based laptop wasted days! So, I wrote a <a href="https://github.com/staydecent/Mud">framework inspired by GAE's webapp</a>, so even though I had to rewrite all the code, at least the concepts were the exact same. I also used <a href="http://www.mongodb.org/">MongoDB</a> to keep my data structures relatively the same. Fullio has seem some huge delays, but it's super close to a beta-launch. If you're interested, please bug me to get it out.</p> <h2>Cook It Local</h2> <p>Holy neglected project, Batman! Food, nature and sustainability seem to be my passions, so it's saddening to see this project sit idly by. Cook It Local, is an ever adapting idea, web app, resource, tool etc. to inspire people to eat and cook with local, seasonal ingredients. So, many mini-apps and components will end up existing. I don't feel GAE allows for rapid, frequent iterations. So, I am creating a set of libraries for rapid prototyping. The base of this endeavor starts with my HTTP router, <a href="https://github.com/staydecent/Gum/blob/master/Gum.php">Gum</a>. I'll soon have a post on <em>rapid prototyping with PHP</em>.</p> <h2>Closed platforms never win</h2> <p>Is that the lesson? Google App Engine is quite an amazing platform. The cost was basically zero to get my ideas up and running&mdash;I've been hosting staydecent.ca for zero cost for over a year now. But, my current emphasis is on flexibility and so I'll continue to move away from App Engine.</p> Responsive Web Design Adrian Unger Sun, 12 Jun 2011 00:00:00 -0700 https://staydecent.ca/code/responsive-web-design https://staydecent.ca/code/responsive-web-design <p>The implementation and advocacy of responsive web design is increasing, and possibly fully manifested in the web design community. Are you taking part?</p> <h3>What Is Responsive Design?</h3> <p>Responsive web design, basically means your website responds to different screen sizes. So, people browsing your site on a Smartphone, Tablet, Netbook or Desktop all get a usable (and hopefully similar, but not exact) experience.</p> <h4>Types of Responses</h4> <p>There are two main ways to respond to various screen sizes and devices, with: <em>responsive designs</em> or <em>adaptive designs</em>. Responsive design usually means a fluid grid, using percentages. See: <a href="http://stephencaver.com/">Stephen Caver's Portfolio</a> and <a href="http://www.miekd.com/">Maykel Loomans' Blog</a>. And, adaptive design usually means you have fixed grid, that adapts (changes) depending on the screen size. See: <a href="http://colly.com/">Mr. Simon Collison</a> and <a href="http://www.authenticjobs.com/">Authentic Jobs</a>. You could also use a combination of both, sort of like my Blog that you’re reading now.</p> <h3>Media Queries</h3> <p>CSS3 media queries, quite literally, let you query different media types, <code>screen</code>, <code>print</code> and <code>handheld</code> as well as other helpful properties such as <code>min-width</code>, <code>max-width</code>, <code>orientation</code> and others. <strong>Media queries easily let you define your CSS for any screen size by querying the <code>min-width</code> and <code>max-width</code>.</strong> So, all you really need to know are the common screen widths. According to <a href="https://twitter.com/#!/bryanrieger/status/75597655870406656">Bryan Rieger</a> the “major breakpoints are 0-320, 320-720, 720+ with minor breakpoints dependent on content and key devices (ie: 360, 480, 768, etc).”</p> <h4>What Does This Mean?</h4> <p>In the below snippet, I have included the exact media queries that I use, as well as a few (one, for now) examples from popular CSS frameworks and authors.</p> <script src="https://gist.github.com/1021805.js?file=media_queries.css"></script> <p>So, if you’re like me and usually develop a new grid for each website you design (which, I highly recommend) those media queries are really helpful in adjusting your design for specific devices and screen widths. And, if you like using boilerplates/frameworks and often design a 960px grid, <a href="http://getskeleton.com">Skeleton</a> is great.</p> <h3>But How Should I Adjust My Design For Each Query</h3> <p>Obviously, you can’t just continuously shrink your column widths—eventually you’d have content trying to fit into 20px columns! So, commonly, you'll end up dropping the number of columns. If you’re full-width design has 6 blocks floating together, you might have to drop that for each query: 4 blocks a row; 3 blocks a row; 2 blocks a row; everything in a single column.</p> <h3>That’s It!</h3> <p>Really. Responsive web design is not much work. I would say, for the bare minimum, design your full width site, Ipad width of 768px and mobile width of 320px.</p> <p>For corrections, comments and questions message me <a href="http://twitter.com/staydecent">@staydecent</a>.</p> Omtask, A Simpler Task List Adrian Unger Wed, 04 May 2011 00:00:00 -0700 https://staydecent.ca/code/omtask-simpler-task-list https://staydecent.ca/code/omtask-simpler-task-list <p>Omtask is an omnibox task manager for people that want to finish tasks, not organize them.</p> <h3>Why Omtask?</h3> <p>When I came across <a href="http://stevelosh.com/projects/t">Steve Losh's t</a>, I loved the idea of it. But, I also realised the extent of my <em>bashing</em> was updating git and svn repositories. Being mostly, a front-end web developer—and addicted to the internet—I spend a huge amount of time in my Web Browser, which happens to be Chrome. <em>Hey, wait a minute! Aren't I able to run commands from Chrome's address bar?</em> Yes! So, I set out to implement the exact same feature set as <code>t</code> in a Google Chrome Extension.</p> <p><em>Not Quite There</em></p> <p>There is no marking tasks as <em>complete</em> and editing still needs to be added. But, you can add tasks, view them, and delete them. All from the Omnibar (this is what Chrome calls its address bar)! But, this is enough functionality for me to already begin using it. I stopped using <a href="http://taskthing.appspot.com">Task Thing</a> awhile ago.</p> <h3>It's So Easy!</h3> <p><code>t Blog about omtask.</code></p> <p>There is no package yet, as I think it needs some more testing and editing of tasks implemented. But, you can check out the source on <a href="https://github.com/staydecent/omtask">GitHub</a>. If you'd like to try it out right away, clone the repo, then on Chrome's Extension page click <em>Developer Mode</em> and <em>Load unpacked extension</em>.</p> Managing Coworking Adrian Unger Sat, 29 Jan 2011 00:00:00 -0800 https://staydecent.ca/code/managing-coworking https://staydecent.ca/code/managing-coworking <p>When I was working in a team of about ~15 at an Advertising Agency, we were commonly trying to perfect how we all interacted with each other.</p> <p>Building off of 37Signals concept that work doesn't get done at work, we wanted to prevent intrusive chit-chatting and undelivered IMs. The main problems were: <strong>Is this person currently in the office? What is the person currently working on? Is this person available to talk about current projects, new projects or other matters?</strong> I recently saw a <a href="http://techcrunch.com/2011/01/05/yammer/">TechCrunch post</a> about <a href="http://yammer.com">Yammer</a> which was a potential solution to those problems that never really worked. It's very hard to integrate <em>yet another</em> app into a teams workflow. We already had Basecamp, Jira, Google Docs, IM, etc. so adding Yammer, which needed to be consciously updated every time someone switch gears (left the office, started a project, switched to another project, had a meeting), had a high barrier for most people.</p> <p>Every team has a suite of apps they use to manage all of their internal workings; the problem of perfecting internal interactions shouldn't be handled by another app to add to the suite. Instead, we should refine the way we access that suite of apps.</p> <h3>The Internal Start Page</h3> <p>Lots of you already use a start page for your web browsing and if you're like me you probably have your business apps (time tracking, invoicing etc.) pinned to your start page for easy access. This has always helped me in remembering to sign into Basecamp and log my hours, or check out the bug tracking app to see what should be resolved today. But, it's not a perfect fit. This is where the <strong>internal start page</strong> comes in.</p> <p><img src="http://lh5.ggpht.com/_OWzPdn_VEvM/TUR-UGUgvQI/AAAAAAAAAA0/yGQmXGploTE/s640/InternalStartPage.png" alt="Internal Start Page porotype" /></p> <p>The above is a very simple prototype, that could potentially solve this inter-office interaction problem. Like the <em>suite</em> offered from 37Signals for accounts using more than one product, there is an area containing unique icons for each app used by a team. This provides the basis of an internal start page. Where it becomes useful in improving interactions with coworker is the team list on the right (this layout would only suffice for small &lt; 25 person teams) where it shows all members of the team, and their current status.</p> <h3>Where's The Magic?</h3> <p>On it's own, this is just the same nuisance as when we tried to use Yammer—each person is required to update their status every time the are busy, available, in office, on the phone, etc. The magic idea is in the <em>portal</em>. Each linked app would have API access (most web based apps for teams have API's). When a person accesses an app and does some kind of unique activity, the <em>start page</em> would know, automatically adjusting that person's status.</p> <h3>Why Am I Sharing This Idea?</h3> <p>This <em>internal start page</em> idea would require a decent barrier to setup each app and team member's account. It would also require a decent amount of programming to make this work. And, could it <em>really</em> work? Let me know what you think <a href="http://twitter.com/staydecent">@staydecent</a>!</p> Being Self Taught Revisted Adrian Unger Wed, 05 Jan 2011 00:00:00 -0800 https://staydecent.ca/blog/being-self-taught-revisted https://staydecent.ca/blog/being-self-taught-revisted <p class="big">A few weeks ago I posted about possible drawbacks of being a self-taught web developer and I got some really good feedback.</p> <p>The two main problems I illustrated were: <strong>How to your asses your own ability and properly convey it</strong> and after assessing your ability <strong>how to properly determine the next step of progression.</strong> I now think both problems are futile. I'm self-taught because I didn't agree with the requirements and structure of schools and assessments are inherently part of schooling&mdash;So, why am I trying to assess myself?</p> <p>You can't just tell people you are an expert; that's for them to determine. Rather, show them what you do, and how it's helped people in the past.</p> <blockquote> <p>&ldquo;I&rsquo;ve never been asked for proof of my qualifications &mdash; my work speaks for itself and the majority of my new work comes from current, happy clients telling others about me.&rdquo; &mdash; <a href="http://www.drawar.com/posts/The-Unforeseen-Consequence-of-Being-Self-Taught#comment-9047">webecho</a></p> </blockquote> <h3>How to properly progress without assessment</h3> <p>Being a self-taught web developer, I already know how to keep up with a radically evolving industry. Where as, graduating from a rigid web design program, you may assume you have reached a certain level of knowledge and skill that will maintain your elligibility in getting work. But, <strong>Regardless of a formal or informal educational background in this field, the technology will permeate anyones&rsquo; experience and knowledge if they don't constantly learn.</strong> Being self-taught, I've become a proactive learner: When I wanted to know how to create a webpage I scoured the internet for tutorials, guides, blog posts and spec sheets.</p> <blockquote> <p>&ldquo;An earnest personal motivation to learn is not something you pick up in a structured learning environment, and this skill will help you stay on top of trends and developments in the field.&ldquo; &mdash; <a href="http://www.drawar.com/posts/The-Unforeseen-Consequence-of-Being-Self-Taught#comment-9046">eggNrice</a></p> </blockquote> <p>However, being solely self-taught may not work for every field related to web design and develoment. When it comes to designers <a href="http://www.drawar.com/posts/The-Unforeseen-Consequence-of-Being-Self-Taught#comment-9072">benek</a> argues:</p> <p><q>&ldquo;[&hellip;] having formal education in design is huge if you&rsquo;re a designer. Most self-taught designers I see with little experience are just copying trendy tutorials online and they have no foundation in the principles of design.&rdquo;</q></p> <p>Though, it's very possible one could also teach themselves the fundamentals. I suppose it's just more common place that purely self-taught designers often miss the foundation of good design.</p> <p>In the end, the educational background of someone shouldn't be the primary tell for their perceived ability. Your passion and hunger within your respective field guarantees much more. It's actually pretty prevalant in the design and web industry that a your work outweighs your educational experience.</p> The Unforeseen Consequence of Being Self-Taught Adrian Unger Sun, 12 Dec 2010 00:00:00 -0800 https://staydecent.ca/blog/consequence-of-being-self-taught https://staydecent.ca/blog/consequence-of-being-self-taught <p>I had yet to notice any drawbacks of working in a field where I have either taught myself what I need to know or learned through work experience. Until now.</p> <p>Hopefully you have realized, that I am a Web Designer &amp; Developer. And, I'll now let you know, that I learned nearly everything for this career with trial &amp; error and the internet. And, perhaps more surprising, I can honestly say that my gateway into this career was playing a <a href=" http://en.wikipedia.org/wiki/Counter-Strike">popular</a> computer game nearly nine years ago.</p> <h3>Becoming A Self-Teacher</h3> <p>Sure, Counter-Strike itself was rather addicting but what really got my attention was all those files (just left there for me to explore!) inside the install directory. There were graphics, sounds, levels and even a unique <strong>scripting language</strong>! So, through the power of the internet, I taught myself how to write Counter-Strike scripts. But, after finding or reading about most of the exploits, scripting became dull—I wasn't actually playing the game that much at this point, so there was no utility left. Soon after, I discovered <a href=" http://en.wikipedia.org/wiki/Wallhack#Wallhacking">hacking</a>. Naturally, I <a href=" http://www.gamedeception.net/">taught</a> myself <strong>how to create multiplayer hacks</strong>. Actually, I even worked on some of most popular public cheats of a rather limited time. From the amazing scripting community to the even more amazing hacking communities, I found a viable way to learn whatever I was interested in. And, I continue this approach even today.</p> <h3>Relevant Lessons</h3> <p>My foray into creating websites was <a href=" http://www.crunchbase.com/company/geocities">Geocities</a>. Thankfully, I desired more control and eventually learned HTML; my resource was the <a href="http://www.htmlgoodies.com/primers/html/">HTML Goodies Primers</a>. Which, looking back on it now, seems like a well structured lesson plan that could resemble what's taught in school. Sadly, I can't recall what my main resource was for learning CSS, but for PHP <a href="http://tizag.com">Tizag</a> covers the basics pretty well. From that point, I had developed a strong enough base, that the rest of my learning could be achieved by reading the <a href=" http://docs.python.org/">docs</a> and <a href="http://dev.w3.org/html5/spec/">spec sheets</a> for the technologies I was interested in.</p> <h3>The Problems</h3> <p>Recently, I was reading a bunch of the latest articles on <a href=" http://www.alistapart.com/">A List Apart</a> and I noticed something I didn't have an answer too. Which was, half the articles seemed useful and applicable while the other half seemed obvious. My opinion is that A List Apart offers the highest level of HTML (and similar technologies) understanding. Which lead to my confusion: are only some of the articles aimed for professionals while others are well-suited for beginners? Or, since after following the HTML Goodies Primers I learned much of everything else <em>as it came up</em> in actual work experience, that my knowledge is scattered? Perhaps, I have an understanding of some seemingly expert-level front-end development concepts, while missing other, intermediate or even beginner-level concepts? At the moment, I can't answer those questions. And, that brings up two problems: <strong>Even though I spend almost every hour living inside Web Development, can I claim expertise?</strong> I don't have any physical or widely-accepted <em>certification</em>—just experience. This is a problem, because I don't want to lie and I don't want to claim more than I mean. Another problem is, where do I go from here? <strong>How do I determine what level of knowledge I have of Web Development, and how do I properly determine the next step of progression?</strong></p> <p>Is anyone else self-taught? Have you found any problems associated with being self-taught? I'd love to hear from you either via <a href="mailto: comments@staydecent.ca">email</a> or <a href=" http://twitter.com/staydecent">Twitter</a>.</p> My First Visit To Seattle Adrian Unger Sun, 28 Nov 2010 00:00:00 -0800 https://staydecent.ca/blog/my-first-visit-to-seattle https://staydecent.ca/blog/my-first-visit-to-seattle <p>Since I missed the chance to see one of my all-time favourite people live, in Vancouver, I had an all-too-good reason to visit Seattle for the first time.</p> <p>Grinderman, the newest project of Nick Cave and most of the Bad Seeds, is finishing up their North American tour. It seems the show in Vancouver sold out too fast for me and, without hesitation, caused me to buy tickets to the Seattle show. Incredibly excited to see Nick Cave in the flesh—I just can't help but enjoy <em>almost</em> everything he produces—I was also excited to visit Seattle for the first time. Which is a strange thing as I have, thanks mostly in part by my Dad, seen more American soil than Canadian.</p> <h3>Belltown</h3> <p>My girlfriend and I decided to stay at the Belltown Inn(in Belltown!), which I booked through Hotels.ca. The process was easy enough, and it landed us right in between the concert Venue and Pike Place Market. The Hotel itself isn't much to talk about: it's clean; friendly staff; free bicycles; whatever. Thanks to Hotels.ca we stayed one night at half price, but I can't see myself going back at full price.</p> <p>Now, the neighbourhood of Belltown is pretty interesting. Though I haven't seen much of Seattle(stayed within Belltown, West Edge and the Seattle Centre) I came to like it immediately. Maybe because it's like Gastown but not dark, dirty &amp; depressing. Belltown is interesting because there is no apparent sign of generic and duplicated business. Actually, from what I saw, Seattle has far less fast-food joints and chain restaurants than Vancouver(I'm probably thinking of Downtown and Gastown). I was really surprised that I only came across two Starbucks, and yet both of them had unique and rather interesting storefronts.</p> <h3>Eating</h3> <p>It was rather easy to find online restaurant recommendations for Seattle and perhaps through instinct shortlisted about 6-8 for my Girlfriend and I to choose from once there. Le Pichet easily got both of us excited and we went for our first meal(brunch/lunch thing) there. Le Pichet serves traditional and regional French food. We shared a plate of charcuterie and a Black Cod, Orange &amp; watercress salad. Awesome. It may not have been the best plate of prepared meats I've had, but it was damn tasty, as was the bread and salad. What I really enjoyed was the atmosphere: totally relaxed, subtle decor, really attentive service and Massive Attack on the playlist.</p> <p>As a snack while browsing the Pike Place Market, I grabbed a BLT from Three Sisters Cafe. Perhaps a bit pricey, but good ingredients and just made simply. No fluff.</p> <p>For dinner, we went to the frequently recommended Zig Zag Cafe. First impressions are tough, and it didn't go too well for this Cafe: a mentally distant hostess, red lighting and purple velvet. Not my vibe. I think the high-mark of this place is the drinks—the beverage menu is massive—but we don't care much for this as we're more interested in food. Oh well, we ordered the Boar Bacon Risotto and Full Quail. The food is well prepared and mostly flavourful. The risotto came with big cubes of Boar, which was great! But, Istill prefer a simple Mushroom risotto. The quail was good…just a bit boring. Maybe, if the skin was crispy, or there was more fat, or a tasty sauce all over it. But it was basically just a seasoned bird on top of some seasoned vegetables. Well made, but not exciting.</p> <h3>Grinderman</h3> <p>We caught Grinderman at the King Cat Theatre, a movie-theatre-turned-venue which works quite well. I'm never really sure how to describe Grinderman. I've heard the term, Garage Rock, thrown around. But it's not exactly the sound I think of when I hear that term. Basically, they're a bunch of bearded baddasses(and Nick) who've been playing music for at least 30 years. Nick Cave's writings and lyrics are usually pretty dark and disturbing, but Grinderman really pushes the dirt. The show was loud, dirty and full of energy—they are just amazing to watch.</p> <h3>I'll be back</h3> <p>I <em>really</em> enjoyed Seattle. I couldn't help but compare it to Vancouver and, though my experience is limited, Seattle is a golden city to me right now. It was just so relaxed: big sidewalks, much less inner city traffic, and just so many <strong>unique</strong> restaurants, cafe's, bars and shops. Walking aimlessly, we never were far from yet another local food spot.</p> <p>Seattle is just easy.</p> Logicalism Over Minimalism Adrian Unger Wed, 08 Sep 2010 00:00:00 -0700 https://staydecent.ca/blog/logicalism-over-minimalism https://staydecent.ca/blog/logicalism-over-minimalism <p class="big">I don't subscribe to any sort of minimalist way of life. But, that word seems to have a meaning that I can often attest to my life. The funny thing about words and their meaning is that they aren't consistent across all means.</p> <p>In my very limited scope of <a href="http://mnmal.org/">minimalist inspiration</a>, <em>the word</em> often is attributed to Apple—or the other way around. I mention this, firstly, because labeling and brands are things I attempt to avoid. Secondly, when I said <em>often</em> I meant blindly and always. If anyone shares this limited scope with me, I would like to let them know: <strong>Minimalism is a jaded word with lost meaning, and is more keen to be a fad or popular tag.</strong> And, on the reverse, Windows is hailed as the anti-christ of minimalism. Don't be fooled.</p> <p>In all senses and progressions of my life, I tend to believe I think about things logically. And especially when I started freelancing. I think logically about the way I <strong>work, and the devices used for work and communication; about food, where it comes from and how it's prepared; material items I own, like my clothing, furniture and other equipment</strong>; and, basically anything else I deal with on a day-to-day basis.</p> <p>I'm going to split up each one of these things into separate posts. And, because Apple, computers and gadgets seemed to spark my definition debacle(maybe not quite <em>that</em> serious), I will start there:</p> <h3>The End Of The Branded, Labeled Minimalism In The Office</h3> <p>These <a href="http://mnmal.org/">blogs</a> and <a href="http://usesthis.com/">semi-popular internet figures</a> will have you believe that you need to own 2 to 4 Apple made products to complete your minimalist lifestyle. Now, they may not make this statement outright, but in their act of sharing their all-too-similar ways of life a very pretty, brushed-steel picture is painted. Actually, <a href="http://www.flickr.com/photos/radiantmark/3267684305/" title="Laptop and desktop? Not very minimal">this picture</a>. And, <a href="http://www.vistaload.de/bilder/arbeitsp2.jpg" title="Laptop and desktop? Not very minimal">this one</a>.</p> <p>In multiple, thousand-word essays these authors have shown that you <em>need</em> an Ikea tabletop, some kind of fancy desk chair, the prominent desk lamp, a mac computer, a mighty mouse(such garbage), a cinema display, an iphone, a sleek dock, an ipod, an ipad, and no one cares anymore.</p> <p>In absolute, hellish contrast I am able to Design(even for print!), write markup, code(in multiple languages!), record, produce, take notes(<em>GASP</em> without Word! And, without awesomely, cult loved &quot;minimal&quot; note taking apps exclusive for some other OS!) all with my…Windows 7 based laptop. Now, I'm not going to go into great detail about how <strong>you can work on windows just as minimally and simply as on a mac</strong>. Because you're a grown-up, and you know that you can have a happy computing life without selling your soul to some <a href="http://microsoft.com">corporation</a> or <a href="http://apple.com">brand</a>. You don't have to do any one thing any one way, for the rest of your life and never fell that way of life. You can adapt. You can stop caring. You can still be efficient.</p> <p>Now, I'd like to believe that people will agree with me that this is a rather unimpressive yet beautiful space to work in:</p> <img src="http://imgur.com/16W6K.jpg" alt="My Current Workspace. I am still looking for a desk." class="photo" /> <p>And now, you may argue &quot;it would look <em>even better</em> with a macpro.&quot; And I retort &quot;Suckas! I don't have an office—I just put my computer away in its hiding place, when I'm finished working.&quot;</p> <p>And even now, you may think that I, the author, has gone astray, and lost his original point. But, I will emphasize that my point is to stop caring. This is so silly. If you <strong>honestly</strong> believe that you cannot share the same minimalist lifestyle of simplicity and happiness and zen and organization and flowing water and grooveshark and starbucks and meetups with a Windows based machine in place of a Macintosh, then you should add the following disclaimer to your blog and every accompanying brand hugging post:</p> <p><strong>I am unwilling to be adaptable. I am unwilling to take matters into my own hand and consider all possibilities. I believe minimalism is always the easiest most obvious solution, and let the past dictate the future. I am set in stone. I am a minimalist without logic.</strong></p> Minor Update to Task Thing Adrian Unger Wed, 01 Sep 2010 00:00:00 -0700 https://staydecent.ca/code/minor-update-task-thing https://staydecent.ca/code/minor-update-task-thing <p>While remaining rather minimal, Task Thing has a new feature—more specifically a helpful piece of data is now displayed on completed tasks.</p> <p>For anyone who is unaware, I created a little app called <a href="http://taskthing.appspot.com">Task Thing</a> a <a href="http://blog.staydecent.ca/entry/task-thing">few months ago</a>. It hasn't gained much traction, but a couple people seem to be using it(Woo-ee!).</p> <p>With the hope that I will be more efficient and precise at tracking my time, <strong>Task Thing now tells you how long it took for you to complete a task</strong>. This functionality was already implemented as Task Thing logs the creation date and last modified date for each task. Using this data, when a task is marked as completed(which logs the time of this action) Task Thing displays that time relative to the time since creation.</p> <p>Because I use Task Thing at a very micro scale—I only add tasks that I am tackling that day, and usually as I begin working on them—I can actually reference this <em>time to complete</em> when logging my hours for the day. Obviously, if I create a task one day, ignore it for a few days, then work on it, and mark it complete, it's not an accurate measure of <strong>actual time</strong> committed to that task. But, still an interesting piece of data. Maybe I should start logging average time to complete tasks?</p> <p><strong><a href="http://taskthing.appspot.com">Try Task Thing today</a></strong></p> Publishing By Email With Google App Engine Adrian Unger Sat, 03 Jul 2010 00:00:00 -0700 https://staydecent.ca/code/publishing-by-email-app-engine https://staydecent.ca/code/publishing-by-email-app-engine <p>I really like the Posterous approach to publishing online—I often write my ideas down in GMail. So I decided to enable posting by email on my blog.</p> <p>The concept needs some work, but could very easily be adapted to a multi-user environment. In that case, some serious security work would be required. But for my personal blog, it should suffice.</p> <h3>How It Works</h3> <p>Google App Engine has amazing Email handling built in. Just check the <a href="http://code.google.com/appengine/docs/python/mail/">docs</a>. Because of this, not much code is required. Anyway, here's what I've accomplished:</p> <ol> <li>Write posts in email</li> <li>Process those emails for <em>YAML Front Matter</em></li> <li>Continue using Markdown</li> </ol> <p>Pretty basic. I haven't got into checking attachments, but I don't think it would be too much more work. As for the <a href="http://wiki.github.com/mojombo/jekyll/yaml-front-matter">YAML Front Matter</a>, a concept taken from <a href="http://jekyllrb.com/">Jekyll</a>, I follow <a href="http://hunch.se/">Rasmus Andersson's</a> formatting exactly as it <a href="http://github.com/rsms/gitblog/blob/master/docs/content.md">appears</a> in <a href="http://github.com/rsms/gitblog">Gitblog</a></p> <h3>How I Did It</h3> <p>I just read through those <a href=" http://code.google.com/appengine/docs/python/mail/">docs</a> I mentioned above and wrote an Email Handler. My blog has a very simple Entry handler, so saving new entries is pretty easy.</p> <script src="http://gist.github.com/462907.js?file=email.py"></script> <p>If you have any questions or input, message me on [Twitter]( <a href="http://twitter.com">http://twitter.com</a> Staydecent on Twitter).</p> Installing App Engine On Windows Adrian Unger Wed, 30 Jun 2010 00:00:00 -0700 https://staydecent.ca/code/installing-app-engine-on-windows https://staydecent.ca/code/installing-app-engine-on-windows <p>The most difficult part of installing Google App Engine on Windows is the SSL module. But I've decided to compile a very simple guide for the whole process.</p> <p>I am not going to cover any sort of usage guides. This is just a list to installing everything required(on Windows) to deploy an App to the GAE cloud.</p> <ol> <li>Download &amp; Install <a href="http://www.python.org/download/releases/2.5">Python25)</a></li> <li>Download &amp; Install <a href="http://code.google.com/appengine/downloads.html">App Engine</a></li> <li>Download &amp; Install <a href="http://beautifulisbetterthanugly.com/s/uploads/python/ssl-1.15.win32-py2.5.exe">Python25 SSL Installer</a></li> </ol> <p>The hardest part: Installing the SSL Module. Python25, unlike 26 and newer, does not come with the SSL Module and must be installed. The normal route of <code>python setup.py install</code> will produce errors. Something about wrong compilers. There are <a href=" http://malei39.blogspot.com/2010/02/install-ssl-module-for-pyhon-254.html">tutorials</a> out there for installing all the dependencies manually. Luckily, someone has created an installer exe. I have tested this on WindowsXP and Windows7 and it works.</p> <h3>32bit Versus 64bit</h3> <p>Do not install the 64 bit version of Python on Windows. If you do you will have to compile everything yourself. Including that installer, that installer is 32bit only. I really don't know any benefit to installing the 64bit version of Python.</p> <p>Unless I am forgetting something, that is all you need.</p> Wordpress Featured Post Slider Adrian Unger Thu, 24 Jun 2010 00:00:00 -0700 https://staydecent.ca/code/wordpress-featured-post-slider https://staydecent.ca/code/wordpress-featured-post-slider <p class="big">WordPress 3 is out: And it makes developing feature rich, user maintainable websites possible with the just the core.</p> <p>WordPress is already known for its ease of development, deployment &amp; maintainability. Well, maybe not always the last one due to unmaintained plugins. This is addressed in WordPress 3.0 by <a href="http://codex.wordpress.org/Version_3.0">adding</a> to the expansive core. Anyway, here's an example of how to build a common blog feature with just core functions and some jQuery.</p> <h3>Featured Image Slider</h3> <div class="aside">Note: Featured Image—as it's called within the admin UI—is synonymous with Post Thumbnail—as it's called in the function references.</div> <p>What is it? It's a way of showcasing all of the posts with a <a href="http://markjaquith.wordpress.com/2009/12/23/new-in-wordpress-2-9-post-thumbnail-images/">featured image</a> in a simple slider (or other jQuery animation). All we have to do, is add support for post thumbnails and display them within the loop, and jQuery will handle the animation.</p> <h3>The WordPress Code</h3> <p>For a deeper explanation of post thumbnails, read <a href="http://markjaquith.wordpress.com/2009/12/23/new-in-wordpress-2-9-post-thumbnail-images/">Mark Jaquith's Post</a>. For now, here is the code to add support and define the sizes of our post thumbnails:</p> <pre><code>add_theme_support( 'post-thumbnails' ); set_post_thumbnail_size( 300, 100, true ); // Normal thumb size add_image_size( 'featured-image', 900, 300, true ); // Slider size</code></pre> <p>I displayed the slider on the homepage only, but pick a theme file and add the following within the loop:</p> <pre><code>&lt;?php if (in_category('10') &amp;&amp; has_post_thumbnail()) : // Category 10 is my 'Featured' category ?&gt; &lt;a href="&lt;?php the_permalink() ?&gt;" title="Permalink to &lt;?php the_title() ?&gt;" rel="bookmark"&gt; &lt;?php the_post_thumbnail('featured-image'); // Make sure you call the image size you defined in functions.php ?&gt; &lt;/a&gt; &lt;?php endif; ?&gt;</code></pre> <h3>The jQuery Code</h3> <p>This is covered everywhere. You can use <a href="http://sorgalla.com/projects/jcarousel/">jCarousel</a> or any other jQuery(or other framework) plugin. Otherwise, check out my live <a href="http://highfivecamp.com">implementation</a> and feel free to view the source.</p> Staying Productive With Task Thing Adrian Unger Tue, 25 May 2010 00:00:00 -0700 https://staydecent.ca/code/task-thing https://staydecent.ca/code/task-thing <p class="big">I have recently jumped back into the freelance world. And I need ways to stay productive.</p> <h3>Why I am freelancing</h3> <p>Growing sick of the <em>office</em> &amp; meetings &amp; commuting &amp; packed lunches &amp; disagreements, I decided to get back into freelancing—effectively taking control of my life. The first day I sat down at my desk, I asked “What the fuck am I supposed to do today?” I needed a list of things(tasks) to keep me in check.</p> <h3>Available tools</h3> <p>Of course, the first thing I did was consider all of the to-do lists and task lists I have used in the past or just heard of(there are lots): <a href="http://todoist.com/">Todoist</a>, too much; <a href="http://tadalist.com/">Ta-da List</a>, I may as well used pen &amp; paper; <a href="http://teuxdeux.com/">Teux Deux</a>, this was a close winner, but I don't like the multiple lists concept, or the small font-size. Naturally, if I wanted something I wouldn't complain about and could use every day, I needed to create my own.</p> <h3>Introducing Task Thing</h3> <p>This brings us to <a href="http://taskthing.appspot.com">Task Thing</a>! I would say this is very similar to Ta-da List, but with actual benefits over using just pen &amp; paper. I say so because of drag &amp; drop, inline editing and an understandable interface. Maybe I'm wrong, but feel free to <a href="http://taskthing.appspot.com">give it a try</a> yourself!</p> <div style="background:url(http://taskthing.appspot.com/goods/png/screen.png);width:500px;height:200px;margin:0 auto 2em;-webkit-box-shadow: rgba(0, 0, 0, 0.199219) 0px 0px 15px;"></div> <h3>Building Task Thing</h3> <p>I built Task Thing over the better part of a day. This was possible because I was using a bunch of code I had written for another concept of mine(Hint: Panic Status Board). I won't go into too much detail, but Task Things' functionality is broken up into two models: list &amp; task. The list model represents the page which gets one owner and any amount of tasks(owned by the same owner). A task has two editable fields, title &amp; description as well as some other internal data(dates, priority, etc). Linking the tasks to the proper list is rather simple: the list attributes a unique slug and owner. When you view that list, you must login as the owner(logging in, you are redirected to your list). The tasks also have an owner field, which is matched with the list. Learning how to link different values in the App Engine datastore has been a lot of fun and so much lighter than MySQL joins. Also, I <a href="http://noahstokes.com/">Ajaxed</a> the shit out of it.</p> <h3>Staying Productive</h3> <p>Creating a task list was the first step I took in helping myself <em>stay productive</em>, and I am sure there will be more. So, if you care, <a href="http://feeds.feedburner.com/staydecent" title="the Staydecent™ Blog feed">check this blog often</a> as I post more things.</p> jQuery Random Each() Function Adrian Unger Fri, 19 Mar 2010 00:00:00 -0700 https://staydecent.ca/code/jquery-random-each https://staydecent.ca/code/jquery-random-each <p class="big">Fading in elements incrementally in order of the dom tree is cool, but so is fading in elements in random order.</p> <p>The former is pretty simple, you iterate through each element while setting a timeout for fading in:</p> <pre><code>$("div").each(function(i) { var e = $(this); e.fadeTo(0, 0.05); setTimeout(function(){ e.fadeTo(250, 1); }, i*25); });</code></pre> <p><code>i</code> is the index of each found element in order of the dom tree. As we get further down the tree the timeout is longer and longer—since the animation lasts longer than a couple timeouts the animations will overlap.</p> <p>To make it random, we still follow the dom tree in order, but we set the timeouts at differentiating lengths(randomly). Say we have 10 elements total, we can assume the indices are <code>0,1,2,3,4,5,6,7,8,9</code>, We just need to sort those numbers randomly. Enter <code>randsort()</code>:</p> <pre><code>function randsort(c) { var o = new Array(); for (var i = 0; i &lt; c; i++) { var n = Math.floor(Math.random()*c); if( jQuery.inArray(n, o) &gt; 0 ) --i; else o.push(n); } return o; }</code></pre> <p>We pass the function the number of found elements and it loops through them creating new numbers(within the range of <code>c</code>). To avoid duplicated numbers we use jQuery's <code>inArray</code> and “skip” it if true. In the end, you have those indices in a random order. Moving along:</p> <pre><code>var e = $('div') // The elements we're searching var c = e.size() // Total number of those elements var r = randsort(c) // an array of the element indices in random order</code></pre> <p>Now an ever so slight variance on that original each function:</p> <pre><code>// the jQuery selector could be replaced with e $("div").each(function(i) { var e = $(this); e.fadeTo(0, 0.05); setTimeout(function(){ e.fadeTo(250, 1); }, r[i]*10); });</code></pre> <p>So what's different? <code>r[i]*10</code>. We are using the <code>i</code> index to call the <code>r</code> array in order, but since the values are a random representation of the element indices the timeouts differentiate. Boom!</p> <p>Check out a <a href="http://staydecent.nfshost.com/demos/js/randomeach.htm">demo here.</a></p> An Introduction Adrian Unger Thu, 18 Mar 2010 00:00:00 -0700 https://staydecent.ca/blog/intro https://staydecent.ca/blog/intro <p class="big">I have relaunched my website and launched my blog as a separate website. Here's how and why.</p> <div class="clearfix"> <div class="col size1of3"> <h3>In The Old Days</h3> <p>A few(or several) years back I had an account at a host named FreePGS, they offered PHP and MySQL at no cost! It housed numerous iterations of my homepage even up until Staydecent. FreePGS' offered service changed numerous times while I was there: From completely free, to $3 a year, to no longer accepting new accounts. Even when they started charging, I won a design contest and got to remain there for free, surviving through the death of FreePGS. In the end, I was plopped onto some reject GoDaddy reseller server that barely had enough power to load Plesk, while they asked me for $3 a year. Eventually, I stopped paying for that account.</p> </div> <div class="col size1of3"> <h3>The Hiatus</h3> <p>I spent too much time researching hosts. Web Faction, Linode, Slicehost, PRGMR, all promising and none were a clear winner for me. So, I ended up with a static landing page for maybe a year? Anyway, I was serving this static page up on Nearly Free Speech, a pay for what you get service. Simple and cheap. Going back to those other hosts: the main reason I was considering them was because I wanted to learn the ins and outs of a VPS(or similarly free[as in freedom] service). But, VPS is dated and <em>The Cloud</em> is in. So, I started playing around with Google App Engine.</p> </div> <div class="col size1of3 last"> <h3>In The Cloud</h3> <p><em>Here's lookin’ at you, kid!</em> What's that mean? Who cares, Rejoice! I built a Blog in Python on GAE.</p> <p>This blog is hosted on App Engine, but what about the portfolio? It's still on Nearly Free Speech, serving up static files. Why not? And, this is the first time I've split my blog away from the main site. Now, I have <strong>two</strong> sites to mess around with, constantly!</p> <p>If you haven't noticed, or realized from this post: I change my website all the time. It constantly evolves as I learn new things and try new things with it. And so will this blog! I will try and be more consistent and make sure permalinks live on and keep downtime to a minimum. And, at least for now, the current Staydecent Blog and Staydecent Portfolio are not going to change much.</p> </div> </div> An Interview With Chris Allen Adrian Unger Wed, 04 Feb 2009 00:00:00 -0800 https://staydecent.ca/blog/interview-chris-allen https://staydecent.ca/blog/interview-chris-allen <p class="big">Chris Allen is a Vancouver based freelance Graphic Designer and Art Director, an Emily Carr Institute of Art and Design graduate and has strong roots in the Skateboarding industry.</p> <p><em>Check out this interview I conducted with him to find out more!</em></p> <img class="photo" src="http://lh6.ggpht.com/_Z_QjhvaYEE4/SYnvFY2fjTI/AAAAAAAAAKk/4fQwJrlXCRY/s800/c-allen02.jpg" /> <h4>Hey Chris, could you tell me a bit about your background(live, born, age, work, school, whatever!)?</h4> <p>Age 31; Work and live in Vancouver, BC Canada; Studied graphic design at ECIAD; Freelance designer currently working with Studio: Blackwell.</p> <h4>What do you think of Vancouver, in terms of graphic design work and whatever else stands out?</h4> <p>Vancouver is a beautiful city and [has] recently been rated as one of the worlds move livable cities. In regards to graphic design, I feel opportunity is a little lacking and as a result Vancouver has an over abundance of interactive studios and advertising agencies. Vancouver is not on the international radar of design hotspots by any means, but I feel confident in saying that good work is good work and can be produced anywhere. At the moment Vancouver seems to be working for me but [I] would love to experience living and working in a large city like London or New York.</p> <h4>Do you remember working for your first client? Anything to tell?</h4> <p>My fist client was a friend who required help in branding a small clothing line he was developing. With no formal training, technically or theoretically the intent was there and at the level we were operating it that was the most important thing. We knew what we wanted to do and how things should look it was just a matter of making it happen. No rationale, no theory—just make it look good. We photographed and produced a brand book/catalogue and developed a logo. It was all very simple but proved to be effective and as a result landing him the Urban Outfitters account. </p> <blockquote class="col size2of5">We knew what we wanted to do and how things should look it was just a matter of making it happen. No rationale, no theory—just make it look good.</blockquote> <h4>I noticed your older work is largely based around the skateboarding and street cultures, how did that come about?</h4> <p>As a freelance designer I try and pursue projects that compliment and reflect my interest. Much like the work I did with Transworld Skateboarding. At that point of my life I was was heavily involved in skateboarding industry and also being a skateboarder myself it was only natural that I pursued work in which I was knowledgeable and had a love for. A Canadian friend of mine was the art director at Transworld in San Diego while I was attending Emily Carr. He contacted me to design an editorial feature figuring I could use the break, not to mention the cash. This proved to be a great way to get my feet wet in editorial design and also achieve a childhood dream of working at a skateboard magazine. </p> <h4>And now, your new work shows some great strategic branding, was this a natural progression moving to that kind of work? Which type of work do you prefer?</h4> <p>I think this is a natural progression for most designers. The more experience a designer gains the more knowledge they can apply to larger more complex projects. Honestly I prefer whatever project allows for the greatest opportunity for a new experience and a chance to create something I have not done before allowing me to constantly progress as a designer. My fear is doing the same thing over and over again, I think that is why I have been so reluctant to work in advertising, I am scared of the formula, the punch lines. </p> <img class="photo" src="http://lh4.ggpht.com/_Z_QjhvaYEE4/SYnvFd91AeI/AAAAAAAAAKs/lMtDTFxdFQM/s800/c-allen03.jpg" /> <img class="photo" src="http://lh3.ggpht.com/_Z_QjhvaYEE4/SYnvFs-L51I/AAAAAAAAAK0/OuKUotaAeiE/s800/c-allen04.jpg" /> <h4>Are you able to tell us about any current or recent projects you are working on?</h4> <p>Currently I am working with Studio: Blackwell designing exhibition catalogues and artist monographs for the Gagosian Gallery and Rizzoli. Kelsey Blackwell is amazing and has taught me so many valuable lessons, not just with regards to design but theory and life itself. I feel honored to have such an incredible mentor. </p> <h4>What would be your ultimate dream project?</h4> <p>At this point I can't really give you a specific answer to that question. I guess my dream project would be to start a small publishing company and work remotely from a detached home studio with floor to ceiling glass in the middle of a forest. </p> <h4>What tracks, artists or albums are you listening to right now?</h4> <p>This is an interview in itself. The following are what I pulled off the records shelf in no particular order:</p> <ul> <li>Led Zeppelin - II </li> <li>Booker T &amp; The M.G.'s - Melting Pot </li> <li>Bob Dylan - Blood On The Tracks </li> <li>Black Sabbath - Sabbath Bloody Sabbath </li> <li>The Doors - Strange Days </li> <li>David Bowie - The Rise And Fall OF Ziggy Stardust And The Spiders From Mars </li> <li>Bill Withers - Still Bill </li> <li>Pink Floyd - Dark Side Of The Moon </li> <li>Heart - Little Queen </li> <li>Jane Birkin, Serge Gainsbourg - Self Titled </li> <li>Santana - Abraxas </li> <li>Unicorn - Tyrannosaurus Rex </li> </ul> <h4>Some Artists, designers, companies your into right now?</h4> <p>There are too many to list but I do find the following people although contemporary very interesting and influential: Storm Thorgerson (Hipgnosis), Bruce Mau Design, Spin, Build, Underline Studio, 2x4, Made Thought, Browns, Pentagram, Experimental Jetset, Non Format, Graphic Thought Facility, NB: Studio........ </p> <h4>The essentials of every day life?</h4> <p>Family, my lovely girlfriend, friends, my animals, nature, food, music, photography, art and design.</p> <p><em>Many thanks to Chris Allen for being my first interviewee! Please check out his <a href="http://christopherallen.ca" target="_blank">website</a> for more work and info.</em></p>