{"rowid": 295, "title": "Internet of Stranger Things", "contents": "This year I\u2019ve been running a workshop about using JavaScript and Node.js to work with all different kinds of electronics on the Raspberry Pi. So especially for 24 ways I\u2019m going to show you how I made a very special Raspberry Pi based internet connected project! And nothing says Christmas quite like a set of fairy lights connected to another dimension1.\nWhat you\u2019ll see\nYou can rig up the fairy lights in your home, with the scrawly letters written under each one. The people from the other side (i.e. the internet) will be able to write messages to you from their browser in real time. In fact why not try it now; check this web page. When you click the lights in your browser, my lights (and yours) will turn on and off in real life! (There may be a queue if there are lots of people accessing it, hit the \u201cSend a message\u201d button and wait your turn.)\n\n\n\n\nIt\u2019s all done with JavaScript, using Node.js running on both the Raspberry Pi and on the server. I\u2019m using WebSockets to communicate in real time between the browser, server and Raspberry Pi.\nWhat you\u2019ll need\n\nRaspberry Pi any of the following models: Zero (will need straight male header pins soldered2 and Micro USB OTG adaptor), A+, B+, 2, or 3\nMicro SD card at least 4Gb Class 10 speed3\nMicro USB power supply at least 2A\nUSB Wifi dongle (unless you have a Pi 3 - that has wifi built in). \nAddressable fairy lights\nLogic level shifter (with pins soldered unless you want to do it!)\nBreadboard\nJumper wires (3x male to male and 4x female to male)\n\nOptional but recommended\n\nBase board to hold the Pi and Breadboard (often comes with a breadboard!)\n\nFind links for where to buy all of these items that goes along with this tutorial. The total price should be around $1004.\nSetting up the Raspberry Pi\nYou\u2019ll need to install the SD card for the Raspberry Pi. You\u2019ll find a link to download a disk image on the support document, ready-made with the Raspbian version of Linux, along with Node.js and all the files you need. Download it and write it to the SD card using the fantastic free software Etcher5. \nNext up you have to configure the wifi details on the SD card. If you plug the card into your computer you should see a drive called BOOT. There\u2019s a text file on there called wpa_supplicant.conf. Open it up in your favourite text editor and replace mywifi and mypassword with your wifi details6.\nnetwork={\n ssid=\"mywifi\"\n psk=\"mypassword\"\n}\nSave the file, eject the card from your computer and plug it into the Raspberry Pi. \nIf you have a base board or holder for the Raspberry Pi, attach it now. Then connect the wifi USB dongle7 and power supply, but don\u2019t plug it in yet!\nWiring!\nTime to wire everything up! \nFirst of all, push the Logic Level Converter into the middle of the breadboard:\n\nLogic Level Converter\nThe logic level converter may be labelled differently from the one in the diagram but the pins are usually exactly the same internally. I would just make sure the pins marked HV (High Voltage) are on the bottom and LV (Low Voltage) are on the top. \n\nRaspberry Pi pins only output 3.3v but the lights need 5v. That\u2019s why we need the logic level converter in there to boost up the signal.\nConnect the first two wires between the Raspberry Pi pins and the breadboard:\n\nNote that the pins on the Raspberry Pi are male, so you need a female to male jumper wire to connect between them and the breadboard. The colours don\u2019t have to match but it\u2019s easier to follow (and check) if you use the same ones as in the diagram. \n\nThen the next two:\n\nThis is what you should have so far:\n\nLights\nNow to connect the lights! My ones have a connector with three holes in it that I can push jumper wires into, and hopefully yours will too! So I used the male-to-male jumper wires to connect them to the breadboard.\n\n\n\nMake sure that you connect the right end of the lights, mine has a male connector at the wrong end so it\u2019s impossible to do this, but double check. \nAlso make sure that the holes in the light connector are the same as mine. To do this, follow the wires from the connector to the first light and look at the circuit board inside. You should just about be able to make out the connections labelled + (sometimes 5V, V+ or VCC), GND (or \u2018-\u2019 or G) and DI (sometimes DIN for data in).\n\nYou can just about make out the +, DI and GND on this picture. Note that on the other side of the board there is a DO for data out - that\u2019s what takes the data along to the chip in the next light. Make sure that you\u2019re plugging into the data-in and not the data-out! \nThat\u2019s it! Everything\u2019s plugged in and ready to go! But before you plug power into your Pi, double check all your wires and make sure they\u2019re exactly right! You could damage your Raspberry Pi if it is not wired correctly. So triple check!\n\nThe Moment of Truth!\nPlug in the Raspberry Pi and wait around a minute or two for it to boot up. If all is well, the lights should strobe rainbow colours for one second - that\u2019s your confirmation that it\u2019s connected to my WebSocket server and ready to receive messages from the upside-down! \n\nHowever, if the first light in the string is pulsing red, it means that you\u2019re not connected to the internet. So check the Troubleshooting section of the support document. If it\u2019s pulsing green then you\u2019re connected to the internet but can\u2019t connect to my server. It must have gone down. Sorry! The code will keep trying so leave it running and maybe it\u2019ll come back up. \nRig up the lights!\nFix the lights up on the wall however you want, pins, nails, tape. I\u2019ve used cable clips. Just be careful! I\u2019m using a 50 light string so I\u2019ve programmed it to use the lights at the end for the letters. That way I have just under half the string to extend down to the floor where I can keep the Raspberry Pi. \nCheck the photo here to see how the lights line up, note that there are spare unused lights in-between each row:\n\nNow visit lights.seb.ly and you\u2019ll see this : \n\nIf you\u2019re the only one online you\u2019ll have direct connection to the lights and any letter you click on will light up both in the browser and in real life. If there are other people there, you\u2019ll need to click the button to join the queue and wait your turn. \nHow it works - the geeky details!\nElectronics:\nThe pins on the Raspberry Pi are known as GPIO pins, general-purpose input/output. You can connect a wide variety of electronic components to them, LED lights, buttons, switches, and sensors. You can turn the power to the pins on and off using Node.js (or Python, if you prefer). \nAddressable LEDs or \u201cNeopixels\u201d\nWe\u2019re only using one GPIO pin on the Raspberry Pi (the other connections are 5V, 3.3V and ground) and that single pin is controlling all of the lights in the string. The code turns the pin on and off really fast in strictly timed morse-code-like dots and dashes to transmit binary data. The chips attached to each LED decode the binary and adjust the output to the LED accordingly. That chip then sends the data on to the next light in the string. \nThe chips on each light are the WS2811, part of the WS281x family that come in a multitude of different form factors and are often packaged with tiny LEDs in a single component. They are commonly referred to as Neopixels8 and I used them on my Laser Light Synths project.\nNeopixels with the chip and the LED all in one - it\u2019s the white square shaped component and the darker square inside is the chip. These are only 5mm wide!\nA Laser Light Synth! Covered with around 800 super bright neopixels!\nLogic Level Converter\nThe logic level converter is a really cheap and easy way to change the level from 3.3v to 5v and back again. You must be careful that you do not connect 5v into a GPIO pin or you will most likely damage the Raspberry Pi processor chip. \nPower\nNeopixels can often draw a lot of current so you need to be careful how you power them. I\u2019ve measured the current draw from the string to be less than 800mA so you should be fine wired directly to the 5V output. But if you use more lights or have them all on really bright at once, you\u2019ll need to use a separate 5V power supply. If you want to learn more, check out Adafruit\u2019s Neopixel Uberguide. \nNode.js\nThere are two Node.js apps running here, one on the Raspberry Pi and one on my server. You can see the code on my GitHub at github.com/sebleedelisle/stranger-lights for the Raspberry Pi and github.com/sebleedelisle/stranger-lights-server for the server. And they\u2019re hosted on npm as stranger-lights and stranger-lights-server. \nThe server side code sets up a standard web server to deliver the HTML for the web interface. It also sets up a WebSocket server that allows for real-time communication between the browser and the server. This server code also manages the queue and who is in control of the lights at any given time.\nWebSockets\nI\u2019m using the excellent Socket.io library to manage the WebSocket connection. Both the browser and the Raspberry Pi Node.js app connects to my WebSocket server. \nWhen you click on a letter in the browser, a message is sent to the server, which forwards it to the connected Raspberry Pi clients and also all the web browsers9. \nThe Raspberry Pi code\nThe Node.js app runs automatically on startup, and I made this happen by adding this to the /etc/rc.local file: \nnode /home/pi/strangerthings/client.js > /dev/null &\nAnything in the rc.local file gets executed when the Pi boots up and this line of code runs the Node.js app and routes its output to nowhere (ie /dev/null). The & means that it runs it in the background and doesn\u2019t hold up the boot process. \nWorking with the Raspberry Pi headless\nYou might know that when a computer has no screen or keyboard, you would refer to it as \u201crunning headless\u201d. So just like most web servers, you need to configure it over the network with ssh10. If you\u2019re on a mac you can find your Pi on the network through the name raspberrypi.local11, otherwise you\u2019ll need to find its IP address. There\u2019s more on the guide to Remote Access instructions on the Raspberry Pi website. And if you\u2019re very new to the terminal, I highly recommend this great online Linux command line tutorial.\nImprovements\nThis is quite an early experiment and I\u2019m sure I\u2019ll discover lots of optimisations over the next few weeks, especially if the server gets a proper hammering today! But there are a few things you can do. Obviously I\u2019ve just rigged up my lights with Post-it notes. It\u2019d be a lot nicer to get a paint brush and try to recreate the Winona-in-a-manic-state text style. \nWhere next?\nFinding quality resources about Node.js for electronics on the Pi can be somewhat hit and miss, but this is getting better all the time. Alternatively I am thinking about running some online courses, please let me know if that\u2019s something you\u2019d be interested in, or sign up to my mailing list at st4i.com. \nThere are many many more resources for the Raspberry Pi with Python (gpiozero is a good place to start), so if that language works for you, you\u2019ll be spoilt for choice! \nAlso take a look at Arduino - it\u2019s an incredibly popular platform for electronics and the internet is literally bursting with resources. \nI hope you enjoyed this little foray into the world of JavaScript electronics on the Raspberry Pi! If you get this working at home please let me know! Tweet me at @seb_ly. \n\n\n\n\nNot a particularly original idea, but I don\u2019t think I\u2019ve seen anyone do it quite like this before, ie using WebSockets, and Node.js on a Raspberry Pi. Other examples: Internet of Stranger Things, Strangerlights.com, and loads of examples on Instructables\u00a0\u21a9\ufe0e\n\n\nVideo guide to soldering pins on to a Pi Zero and further soldering advice from Adafruit\u00a0\u21a9\ufe0e\n\n\nSlower cards will work but performance may suffer\u00a0\u21a9\ufe0e\n\n\nOr \u00a35,000 in UK money. Sorry, Brexit joke :)\u00a0\u21a9\ufe0e\n\n\nYou will need a card reader on your computer - most micro SD cards come with an adaptor that fits standard SD slots. \u00a0\u21a9\ufe0e\n\n\nSSID and password should be all that you need but you can see all the config options on this wpa supplicant guide\u00a0\u21a9\ufe0e\n\n\nRaspberry Pi Zero will require the OTG to USB adaptor to attach the wifi dongle\u00a0\u21a9\ufe0e\n\n\nThanks to Adafruit who invented the term neopixels so we don\u2019t have to refer to them as WS281x any more!\u00a0\u21a9\ufe0e\n\n\nSo you can see other people sending messages in the browser\u00a0\u21a9\ufe0e\n\n\nssh is short for Secure Shell and is a way to connect to a remote computer and type in it just like you would in the terminal.\u00a0\u21a9\ufe0e\n\n\nYou can change this default hostname using raspi-config\u00a0\u21a9\ufe0e", "year": "2016", "author": "Seb Lee-Delisle", "author_slug": "sebleedelisle", "published": "2016-12-01T00:00:00+00:00", "url": "https://24ways.org/2016/internet-of-stranger-things/", "topic": "code"} {"rowid": 293, "title": "A Favor for Your Future Self", "contents": "We tend to think about the future when we build things. What might we want to be able to add later? How can we refactor this down the road? Will this be easy to maintain in six months, a year, two years? As best we can, we try to think about the what-ifs, and build our websites, systems, and applications with this lens. \nWe comment our code to explain what we knew at the time and how that impacted how we built something. We add to-dos to the things we want to change. These are all great things! Whether or not we come back to those to-dos, refactor that one thing, or add new features, we put in a bit of effort up front just in case to give us a bit of safety later.\nI want to talk about a situation that Past Alicia and Team couldn\u2019t even foresee or plan for. Recently, the startup I was a part of had to remove large sections of our website. Not just content, but entire pages and functionality. It wasn\u2019t a very pleasant experience, not only for the reason why we had to remove so much of what we had built, but also because it\u2019s the ultimate \u201cI really hope this doesn\u2019t break something else\u201d situation. It was a stressful and tedious effort of triple checking that the things we were removing weren\u2019t dependencies elsewhere. To be honest, we wouldn\u2019t have been able to do this with any amount of success or confidence without our test suite.\nWriting tests for code is one of those things that developers really, really don\u2019t want to do. It\u2019s one of the easiest things to cut in the development process, and there\u2019s often a struggle to have developers start writing tests in the first place. One of the best lessons the web has taught us is that we can\u2019t, in good faith, trust the happy path. We must make sure ourselves, and our users, aren\u2019t in a tough spot later on because we only thought of the best case scenarios.\nJavaScript\nRegardless of your opinion on whether or not everything needs to be built primarily with JavaScript, if you\u2019re choosing to build a JavaScript heavy app, you absolutely should be writing some combination of unit and integration tests.\nUnit tests are for testing extremely isolated and small pieces of code, which we refer to as the units themselves. Great for reused functions and small, scoped areas, this is the closest you examine your code with the testing microscope. For example, if we were to build a calculator, the most minute piece we could test could be the basic operations.\n/*\n * This example uses a test framework called Jasmine\n */\n\ndescribe(\"Calculator Operations\", function () {\n\n it(\"Should add two numbers\", function () {\n\n // Say we have a calculator\n Calculator.init();\n\n // We can run the function that does our addition calculation...\n var result = Calculator.addNumbers(7,3);\n\n // ...and ensure we're getting the right output\n expect(result).toBe(10);\n\n });\n});\nEven though these teeny bits work in isolation, we should ensure that connecting the large pieces work, as well. This is where integration tests excel. These tests ensure that two or more different areas of code, that may not directly know about each other, still behave in expected ways. Let\u2019s build upon our calculator - we may want the operations to be saved in memory after a calculation runs. This isn\u2019t as suited for a unit test because there are a few other moving pieces involved in the process (the calculations, checking if the result was an error, etc.).\n it(\u201cShould remember the last calculation\u201d, function () {\n\n // Run an operation\n Calculator.addNumbers(7,10);\n\n // Expect something else to have happened as a result\n expect(Calculator.updateCurrentValue).toHaveBeenCalled();\n expect(Calculator.currentValue).toBe(17);\n });\nUnit and integration tests provide assurance that your hand-rolled JavaScript should, for the most part, never fail in a grand fashion. Although it still might happen, you could be able to catch problems way sooner than without a test suite, and hopefully never push those failures to your production environment.\nInterfaces\nRegardless of how you\u2019re building something, it most definitely has some kind of interface. Whether you\u2019re using a very barebones structure, or you\u2019re leveraging a whole design system, these things can be tested as well.\nAcceptance testing helps us ensure that users can get from point A to point B within our web things, which can provide assurance that major features are always functioning properly. By simulating user input and data entry, we can go through whole user workflows to test for both success and failure scenarios. These are not necessarily for simulating edge-case scenarios, but rather ensuring that our core offerings are stable.\nFor example, if your site requires signup, you want to make sure the workflow is behaving as expected - allowing valid information to go through signup, while invalid information does not let you progress.\n/*\n * This example uses Jasmine along with an add-on called jasmine-integration\n */\n\ndescribe(\"Acceptance tests\", function () {\n\n // Go to our signup page\n var page = visit(\"/signup\");\n\n // Fill our signup form with invalid information\n page.fill_in(\"input[name='email']\", \"Not An Email\");\n page.fill_in(\"input[name='name']\", \"Alicia\");\n page.click(\"button[type=submit]\");\n\n // Check that we get an expected error message\n it(\"Shouldn't allow signup with invalid information\", function () {\n expect(page.find(\"#signupError\").hasClass(\"hidden\")).toBeFalsy();\n });\n\n // Now, fill our signup form with valid information\n page.fill_in(\"input[name='email']\", \"thisismyemail@gmail.com\");\n page.fill_in(\"input[name='name']\", \"Gerry\");\n page.click(\"button[type=submit]\");\n\n // Check that we get an expected success message and the error message is hidden\n it(\"Should allow signup with valid information\", function () {\n expect(page.find(\"#signupError\").hasClass(\"hidden\")).toBeTruthy();\n expect(page.find(\"#thankYouMessage\").hasClass(\"hidden\")).toBeFalsy();\n });\n});\nIn terms of visual design, we\u2019re now able to take snapshots of what our interfaces look like before and after any code changes to see what has changed. We call this visual regression testing. Rather than being a pass or fail test like our other examples thus far, this is more of an awareness test, intended to inform developers of all the visual differences that have occurred, intentional or not. Developers may accidentally introduce a styling change or fix that has unintended side effects on other areas of a website - visual regression testing helps us catch these sooner rather than later. These do require a bit more consistent grooming than other tests, but can be valuable in major CSS refactors or if your CSS is generally a bit like Jenga.\nTools like PhantomCSS will take screenshots of your pages, and do a visual comparison to check what has changed between two sets of images. The code would look something like this:\n/*\n * This example uses PhantomCSS\n */\n\ncasper.start(\"/home\").then(function(){\n\n // Initial state of form\n phantomcss.screenshot(\"#signUpForm\", \"sign up form\");\n\n // Hit the sign up button (should trigger error)\n casper.click(\"button#signUp\");\n\n // Take a screenshot of the UI component\n phantomcss.screenshot(\"#signUpForm\", \"sign up form error\");\n\n // Fill in form by name attributes & submit\n casper.fill(\"#signUpForm\", {\n name: \"Alicia Sedlock\",\n email: \"alicia@example.com\"\n }, true);\n\n // Take a second screenshot of success state\n phantomcss.screenshot(\"#signUpForm\", \"sign up form success\");\n});\nYou run this code before starting any development, to create your baseline set of screen captures. After you\u2019ve completed a batch of work, you run PhantomCSS again. This will create a second batch of screenshots, which are then put through an image comparison tool to display any differences that occurred. Say you changed your margins on our form elements \u2013 your image diff would look something like this:\n\nThis is a great tool for ensuring not just your site retains its expected styling, but it\u2019s also great for ensuring nothing accidentally changes in the living style guide or modular components you may have developed. It\u2019s hard to keep eagle eyes on every visual aspect of your site or app, so visual regression testing helps to keep these things monitored.\nConclusion\nThe shape and size of what you\u2019re testing for your site or app will vary. You may not need lots of unit or integration tests if you don\u2019t write a lot of JavaScript. You may not need visual regression testing for a one page site. It\u2019s important to assess your codebase to see which tests would provide the most benefit for you and your team.\nWriting tests isn\u2019t a joy for most developers, myself included. But I end up thanking Past Alicia a lot when there are tests, because otherwise I would have introduced a lot of issues into codebases. Shipping code that\u2019s broken breaks trust with our users, and it\u2019s our responsibility as developers to make sure that trust isn\u2019t broken. Testing shouldn\u2019t be considered a \u201cnice to have\u201d - it should be an integral piece of our workflow and our day-to-day job.", "year": "2016", "author": "Alicia Sedlock", "author_slug": "aliciasedlock", "published": "2016-12-03T00:00:00+00:00", "url": "https://24ways.org/2016/a-favor-for-your-future-self/", "topic": "code"} {"rowid": 303, "title": "We Need to Talk About Technical Debt", "contents": "In my work with clients, a lot of time is spent assessing old, legacy, sprawling systems and identifying good code, bad code, and technical debt.\nOne thing that constantly strikes me is the frequency with which bad code and technical debt are conflated, so let me start by saying this:\nNot all technical debt is bad code, and not all bad code is technical debt.\nSometimes your bad code is just that: bad code. Calling it technical debt often feels like a more forgiving and friendly way of referring to what may have just been a poor implementation or a substandard piece of work.\nIt is an oft-misunderstood phrase, and when mistaken for meaning \u2018anything legacy or old hacky or nasty or bad\u2019, technical debt is swept under the carpet along with all of the other parts of the codebase we\u2019d rather not talk about, and therein lies the problem.\nWe need to talk about technical debt.\nWhat We Talk About When We Talk About Technical Debt\nThe thing that separates technical debt from the rest of the hacky code in our project is the fact that technical debt, by definition, is something that we knowingly and strategically entered into. Debt doesn\u2019t happen by accident: debt happens when we choose to gain something otherwise-unattainable immediately in return for paying it back (with interest) later on.\nAn Example\nYou\u2019re a front-end developer working on a SaaS product, and your sales team is courting a large customer \u2013 a customer so large that you can\u2019t really afford to lose them. The customer tells you that as long as you can allow them to theme your SaaS application according to their branding, they are willing to sign on the dotted line\u2026 the problem being that your CSS architecture was never designed to incorporate theming at all, and there isn\u2019t currently a nice, clean way to incorporate a theme into the codebase.\nYou and the business make the decision that you will hack a theme into the product in two days. It\u2019s going to be messy, it\u2019s going to be ugly, but you can\u2019t afford to lose a huge customer just because your CSS isn\u2019t quite right, right now. This is technical debt.\nYou deliver the theme, the customer signs up, and everyone is happy. Except you (and the business, because you are one and the same) have a decision to make:\n\nDo we go back and build theming into the CSS architecture as a first-class citizen, porting the hacked theme back into a codified and formal framework?\nDo we carry on as we are? Things are working okay, and the customer paid up, so is there any reason to invest time and effort into things after we (and the customer) got what we wanted?\n\nOption 1 is choosing to pay off your debts; Option 2 is ignoring your repayments.\nWith Option 1, you\u2019re acknowledging that you did what you could given the constraints, but, free of constraints, you\u2019d have done something different. Now, you are choosing to implement that something different.\nWith Option 2, however, you are avoiding your responsibility to repay your debt, and you are letting interest accrue. The problem here is that\u2026\n\nyour SaaS product now offers theming to one of your customers;\nanother potential customer might also demand the ability to theme their instance of your product;\nyou can\u2019t refuse them that request, nor can you quickly fulfil it;\nyou hack in another theme, thus adding to the balance of your existing debt;\nand so on (plus interest) for every subsequent theme you need to implement.\n\nHere you have increased entropy whilst making little to no attempt to address what you already knew to be problems.\nYour second, third, fourth, fifth request for theming will be hacked on top of your hack, further accumulating debt whilst offering nothing by way of a repayment. After a long enough period, the code involved will get so unwieldy, so hard to work with, that you are forced to tear it all down and start again, and the most painful part of this is that you\u2019re actually paying off even more than your debt repayments would have been in the first place. Two days of hacking plus, say, five days of subsequent refactoring, would still have been substantially less than the weeks you will now have to spend rewriting your CSS to fix and incorporate the themes properly. You\u2019ve made a loss; your strategic debt ultimately became a loss-making exercise.\nThe important thing to note here is that you didn\u2019t necessarily write bad code. You knew there were two options: the quick way and the correct way. The decision to take the quick route was a definite choice, because you knew there was a better way. Implementing the better way is your repayment.\nGood Debt and Bad Debt\nTechnical debt is acceptable as long as you have intentions to settle; it can be a valuable solution to a business problem, provided the right approach is taken afterwards. That doesn\u2019t, however, mean that all debt is born equal. Just as in real life, there is good debt and there is bad debt.\nGood debt might be\u2026\n\na mortgage;\na student loan, or;\na business loan.\n\nThese are types of debt that will secure you the means of repaying them. These are well considered debts whose very reason for being will allow you to make the money to pay them off\u2014they have real, tangible benefit.\nA business loan to secure some equipment and premises will allow you to start an enterprise whose revenue will allow you to pay that debt back; a student loan will allow you to secure the kind of job that has the ability to pay a student loan back.\nThese kinds of debt involve a considered and well-balanced decision to acquire something in the short term in the knowledge that you will have the means, in the long term, to pay it back.\nConversely, bad debt might be\u2026\n\nborrowing $1,000 from a loan shark so you can go to Vegas, or;\ntaking out a payday loan in order to buy a new television.\n\nBoth of these kinds of debt will leave you paying for things that didn\u2019t provide you a way of earning your own capital. That is to say, the loans taken did not secure anything that would help pay off said loans. These are bad debts that will usually provide a net loss. You really are only gaining the short term in exchange for a long term financial responsibility: i.e., was it worth it?\nA good litmus test for debt is to compare the gains of its immediate benefit with the cost of its long term commitment.\nThe earlier example of theming a site is a good debt, provided we are keeping up our repayments (all debt is bad debt if you don\u2019t). A calculated decision to do something \u2018wrong\u2019 in the short term with the promise of better payoffs later on.\nBad Technical Debt\nThe majority of my work is with front-end development teams\u2014CSS is what I do. To that end, the most succinct example of technical debt for that audience is simply:\n!important\nAll front-end developers know the horrors and dangers associated with using !important, yet we continue to use it. Why?\nIt\u2019s not necessarily because we\u2019re bad developers, but because we see a shortcut. !important is usually implemented as a quick way out of a sticky specificity situation. We could spend the rest of the day refactoring our CSS to fix the issue at its source, or we can spend mere seconds typing the word !important and patch over the symptoms.\nThis is us making an explicit decision to do something less than ideal now in exchange for immediate benefit. After all, refactoring our CSS will take a lot more time, and will still only leave us with the same outcome that the vastly quicker !important solution will, so it seems to make better business sense.\nHowever, this is a bad debt. !important takes seconds to implement but weeks to refactor. The cost of refactoring this back out later will be an order of magnitude higher than it would be to have done things properly the first time. The first !important usually sets a precedent, and subsequent developers are likely to have to use it themselves in order to get around the one that you left.\nSo many CSS projects deteriorate because of this one simple word, and rewrites become more and more imminent. That makes it possibly the most costly 10 bytes a CSS developer could ever write.\nBad Code\nNow we\u2019ve got a good idea of what constitutes technical debt, let\u2019s take a look at what constitutes bad code. Something I hear time and time again in my client work goes a little like this:\n\nWe\u2019ve amassed a lot of technical debt and we\u2019d like to get a strategy in place\nto begin dealing with it.\n\nWhilst I genuinely admire their willingness to identify and desire to fix problems in their code, sometimes they\u2019re not looking at technical debt at\nall\u2014sometimes they\u2019re just looking at bad code, plain and simple.\nWhere technical debt is knowing that there\u2019s a better way, but the quicker way makes more sense right now, bad code is not caring if there\u2019s a better way at all.\nAgain, looking at a CSS-specific world, a lot of bad code is contributed by non-front-end developers with little training, appreciation, or even respect for the front-end landscape. Writing code with reckless abandon should not be described as technical debt, because to do so would imply that\u2026\n\nthe developers knew they were implementing a sub-par solution, but\u2026\nthe developers also knew that a better solution was out there, which\u2026\nimplies that it can be tidied up relatively simply.\n\nDevelopers writing bad code is a larger and more cultural problem that requires a lot more effort to fix. Hopefully\u2014and usually\u2014bad code is in the minority, but it helps to be objective in identifying and solving it. Bad code usually doesn\u2019t happen for a good enough reason, and is therefore much harder to justify.\nTechnical debt often represents ability in judgement, whereas bad code often represents a gap in skills.\nTakeaway\nTake time to familiarise yourself with the true concepts underlying technical debt and why it exists. Understand that technical debt can be good or bad. Admit that sometimes code is just of poor quality.\nUnderstanding these points will allow you to make better calls around what you might need to refactor and when, and what skills gaps you might have in your team.\n\nSometimes it\u2019s okay to cut corners if there is a tangible gain to be had in the immediate term.\nTechnical debt is okay provided it is a sensible debt and you have intentions to pay it off.\nTechnical debt is not necessarily synonymous with bad code, and bad code isn\u2019t necessarily technical debt. Technical debt is code that was implemented given limited knowledge or resource, with the understanding that you would need to repay something in future.\nTechnical debt is not inherently bad\u2014failure to make repayments is. Periodically, it is justifiable\u2014encouraged, even\u2014to enter a debt in order to fulfil a more pressing matter. However, it is imperative that we begin making repayments as soon as we are capable, be that based on newly available time or knowledge.\nBad code is worse than technical debt as it represents a lack of knowledge or quality control within a team. It needs a much more fundamental fix.", "year": "2016", "author": "Harry Roberts", "author_slug": "harryroberts", "published": "2016-12-05T00:00:00+00:00", "url": "https://24ways.org/2016/we-need-to-talk-about-technical-debt/", "topic": "code"} {"rowid": 308, "title": "How to Make a Chrome Extension to Delight (or Troll) Your Friends", "contents": "If you\u2019re like me, you grew up drawing mustaches on celebrities. Every photograph was subject to your doodling wrath, and your brilliance was taken to a whole new level with computer programs like Microsoft Paint. The advent of digital cameras meant that no one was safe from your handiwork, especially not your friends. And when you finally got your hands on Photoshop, you spent hours maniacally giggling at your artistic genius. \nBut today is different. You\u2019re a serious adult with important things to do and a reputation to uphold. You keep up with modern web techniques and trends, and have little time for fun other than a random Giphy on Slack\u2026 right? \nNope. \nIf there\u2019s one thing 2016 has taught me, it\u2019s that we\u2014the self-serious, world-changing tech movers and shakers of the universe\u2014haven\u2019t changed one bit from our younger, more delightable selves.\nHow do I know? This year I created a Chrome extension called Tabby Cat and watched hundreds of thousands of people ditch productivity for randomly generated cats. Tabby Cat replaces your new tab page with an SVG cat featuring a silly name like \u201cStinky Dinosaur\u201d or \u201cTiny Potato\u201d. Over time, the cats collect goodies that vary in absurdity from fishbones to lawn flamingos to Raybans. Kids and adults alike use this extension, and analytics show the majority of use happens Monday through Friday from 9-5. The popularity of Tabby Cat has convinced me there\u2019s still plenty of room in our big, grown-up hearts for fun.\n\n\nToday, we\u2019re going to combine the formula behind Tabby Cat with your intrinsic desire to delight (or troll) your friends, and create a web app that generates your friends with random objects and environments of your choosing. You can publish it as a Chrome extension to replace your new tab, or simply host it as a website and point to it with the New Tab Redirect extension. \nHere\u2019s a sneak peek at my final result featuring my partner, my cat, and I in cheerfully weird accessories. Your result will look however you want it to.\n\nAlong the way, we\u2019ll cover how to build a Chrome extension that replaces the new tab page, and explore ways to program randomness into your work to create something truly delightful. \nWhat you\u2019ll need\n\nAdobe Illustrator (or a similar illustration program to export PNG)\nSome images of your friends\nA text editor\n\nNote: This can be as simple or as complex as you want it to be. Most of the application is pre-built so you can focus on kicking back and getting in touch with your creative side. If you want to dive in deeper, you\u2019ll find ways to do it.\nGetting started\n\nDownload a local copy of the boilerplate for today\u2019s tutorial here, and open it in a text editor. Inside, you\u2019ll find a simple web app that you can run in Chrome. \nOpen index.html in Chrome. You should see a grey page that says \u201cNoname\u201d.\nOpen template.pdf in Adobe Illustrator or a similar program that can export PNG. The file contains an artboard measuring 800px x 800px, with a dotted blue outline of a face. This is your template.\n\nNote: We\u2019re using Google Chrome to build and preview this application because the end-result is a Chrome extension. This means that the application isn\u2019t totally cross-browser compatible, but that\u2019s okay.\nStep 1: Gather your friends\nThe first thing to do is choose who your muses are. Since the holidays are upon us, I\u2019d suggest finding inspiration in your family.\nCreate your artwork\nFor each person, find an image where their face is pointed as forward as possible. Place the image onto the Artwork layer of the Illustrator file, and line up their face with the template. Then, rename the artboard something descriptive like face_bob. Here\u2019s my crew:\nAs you can see, my use of the word \u201cfamily\u201d extends to cats. There\u2019s no judgement here.\nNotice that some of my photos don\u2019t completely fill the artboard\u2013that\u2019s fine. The images will be clipped into ovals when they\u2019re rendered in the application.\nNow, export your images by following these steps:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your faces. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your images to config.js\nOpen scripts/config.js. This is where you configure your extension. \nAdd key value pairs to the faces object. The key should be the person\u2019s name, and the value should be the filepath to the image.\nfaces: {\n leslie: 'images/face_leslie.png',\n kyle: 'images/face_kyle.png',\n beep: 'images/face_beep.png'\n}\nThe application will choose one of these options at random each time you open a new tab. This pattern is used for everything in the config file. You give the application groups of choices, and it chooses one at random each time it loads. The only thing that\u2019s special about the faces object is that person\u2019s name will also be displayed when their face is chosen.\nNow, when you refresh the project in Chrome, you should see one of your friends along with their name, like this:\n\nCongrats, you\u2019re off and running!\nStep 2: Add adjectives\nNow that you\u2019ve loaded your friends into the application, it\u2019s time to call them names. This step definitely yields the most laughs for the least amount of effort.\nAdd a list of adjectives into the prefixes array in config.js. To get the words flowing, I took inspiration from ways I might describe some of my relatives during a holiday gathering\u2026\nprefixes: [\n 'Loving',\n 'Drunk',\n 'Chatty',\n 'Merry',\n 'Creepy',\n 'Introspective',\n 'Cheerful',\n 'Awkward',\n 'Unrelatable',\n 'Hungry',\n ...\n]\nWhen you refresh Chrome, you should see one of these words prefixed before your friend\u2019s name. Voila!\n\nStep 3: Choose your color palette\nReal talk: I\u2019m bad at choosing color palettes, so I have a trick up my sleeve that I want to share with you. If you\u2019ve been blessed with the gift of color aptitude, skip ahead.\nHow to choose colors\nTo create a color palette, I start by going to a Coolors.co, and I hit the spacebar until I find a palette that I like. We need a wide gamut of hues for our palette, so lock down colors you like and keep hitting the spacebar until you find a nice, full range. You can use as many or as few colors as you like.\nCopy these colors into your swatches in Adobe Illustrator. They\u2019ll be the base for any illustrations you create later.\nNow you need a set of background colors. Here\u2019s my trick to making these consistent with your illustration palette without completely blending in. Use the \u201cAdjust Palette\u201d tool in Coolors to dial up the brightness a few notches, and the saturation down just a tad to remove any neon effect. These will be your background colors.\n\nAdd your background colors to config.js\nCopy your hex codes into the bgColors array in config.js.\nbgColors: [\n '#FFDD77',\n '#FF8E72',\n '#ED5E84',\n '#4CE0B3',\n '#9893DA',\n ...\n]\nNow when you go back to Chrome and refresh the page, you\u2019ll see your new palette!\n\nStep 4: Accessorize\nThis is the fun part. We\u2019re going to illustrate objects, accessories, lizards\u2014whatever you want\u2014and layer them on top of your friends.\nYour objects will be categorized into groups, and one option from each group will be randomly chosen each time you load the page. Think of a group like \u201chats\u201d or \u201cglasses\u201d. This will allow combinations of accessories to show at once, without showing two of the same type on the same person.\nCreate a group of accessories\nTo get started, open up Illustrator and create a new artboard out of the template. Think of a group of objects that you can riff on. I found hats to be a good place to start. If you don\u2019t feel like illustrating, you can use cut-out images instead.\n\nNext, follow the same steps as you did when you exported the faces. Here they are again:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your hats. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your accessories to config.js\nIn config.js, add a new key to the customProps object that describes the group of accessories that you just created. Its value should be an array of the filepaths to your images. This is my hats array:\ncustomProps: {\n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ]\n}\nRefresh Chrome and behold, accessories!\n\nCreate as many more accessories as you want\nRepeat the steps above to create as many groups of accessories as you want. I went on to make glasses and hairstyles, so my final illustrator file looks like this:\n\nThe last step is adding your new groups to the config object. List your groups in the order that you want them to be stacked in the DOM. My final output will be hair, then hats, then glasses:\ncustomProps: {\n hair: [ \n 'images/hair_bowl.png',\n 'images/hair_bob.png'\n ], \n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ],\n glasses: [\n 'images/glasses_aviators.png',\n 'images/glasses_monacle.png'\n ]\n}\nAnd, there you have it! Randomly generated friends with random accessories. \n\nFeel free to go much crazier than I did. I considered adding a whole group of animals in celebration of the new season of Planet Earth, or even adding Sir David Attenborough himself, or doing a bit of role reversal and featuring the animals with little safari hats! But I digress\u2026\nStep 5: Publish it\nIt\u2019s time to put this in your new tabs! You have two options:\n\nPublish it as a Chrome extension in the Chrome Web Store.\nHost it as a website and point to it with the New Tab Redirect extension.\n\nToday, we\u2019re going to cover Option #1 because I want to show you how to make the simplest Chrome extension possible. However, I recommend Option #2 if you want to keep your project private. Every Chrome extension that you publish is made publicly available, so unless your friends want their faces published to an extension that anyone can use, I\u2019d suggest sticking to Option #2.\nHow to make a simple Chrome extension to replace the new tab page\nAll you need to do to make your project into a Chrome extension is add a manifest.json file to the root of your project with the following contents. There are plenty of other properties that you can add to your manifest file, but these are the only ones that are required for a new tab replacement:\n{\n \"manifest_version\": 2,\n \"name\": \"Your extension name\",\n \"version\": \"1.0\",\n \"chrome_url_overrides\" : {\n \"newtab\": \"index.html\"\n }\n}\nTo test your extension, you\u2019ll need to run it in Developer Mode. Here\u2019s how to do that:\n\nGo to the Extensions page in Chrome by navigating to chrome://extensions/.\nTick the checkbox in the upper-right corner labelled \u201cDeveloper Mode\u201d.\nClick \u201cLoad unpacked extension\u2026\u201d and select this project.\nIf everything is running smoothly, you should see your project when you open a new tab. If there are any errors, they should appear in a yellow box on the Extensions page.\n\nVoila! Like I said, this is a very light example of a Chrome extension, but Google has tons of great documentation on how to take things further. Check it out and see what inspires you.\nShare the love\nNow that you know how to make a new tab extension, go forth and create! But wield your power responsibly. New tabs are opened so often that they\u2019ve become a part of everyday life\u2013just consider how many tabs you opened today. Some people prefer to-do lists in their tabs, and others prefer cats. \nAt the end of the day, let\u2019s make something that makes us happy. Cheers!", "year": "2016", "author": "Leslie Zacharkow", "author_slug": "lesliezacharkow", "published": "2016-12-08T00:00:00+00:00", "url": "https://24ways.org/2016/how-to-make-a-chrome-extension/", "topic": "code"} {"rowid": 307, "title": "Get the Balance Right: Responsive Display Text", "contents": "Last year in 24 ways I urged you to Get Expressive with Your Typography. I made the case for grabbing your readers\u2019 attention by setting text at display sizes, that is to say big. You should consider very large text in the same way you might a hero image: a picture that creates an atmosphere and anchors your layout.\nWhen setting text to be read, it is best practice to choose body and subheading sizes from a pre-defined scale appropriate to the viewport dimensions. We set those sizes using rems, locking the text sizes together so they all scale according to the page default and your reader\u2019s preferences. You can take the same approach with display text by choosing larger sizes from the same scale.\nHowever, display text, as defined by its purpose and relative size, is text to be seen first, and read second. In other words a picture of text. When it comes to pictures, you are likely to scale all scene-setting imagery - cover photos, hero images, and so on - relative to the viewport. Take the same approach with display text: lock the size and shape of the text to the screen or browser window.\nIntroducing viewport units\nWith CSS3 came a new set of units which are locked to the viewport. You can use these viewport units wherever you might otherwise use any other unit of length such as pixels, ems or percentage. There are four viewport units, and in each case a value of 1 is equal to 1% of either the viewport width or height as reported in reference1 pixels:\n\nvw - viewport width,\nvh - viewport height,\nvmin - viewport height or width, whichever is smaller\nvmax - viewport height or width, whichever is larger\n\nIn one fell swoop you can set the size of a display heading to be proportional to the screen or browser width, rather than choosing from a scale in a series of media queries. The following makes the heading font size 13% of the viewport width:\nh1 {\n font-size: 13 vw;\n}\nSo for a selection of widths, the rendered font size would be:\nRendered font size (px)\nViewport width\n13\u202fvw\n320\n42\n768\n100\n1024\n133\n1280\n166\n1920\n250\n\nA problem with using vw in this manner is the difference in text block proportions between portrait and landscape devices. Because the font size is based on the viewport width, the text on a landscape display is far bigger than when rendered on the same device held in a portrait orientation. \nLandscape text is much bigger than portrait text when using vw units.\nThe proportions of the display text relative to the screen are so dissimilar that each orientation has its own different character, losing the inconsistency and considered design you would want when designing to make an impression.\nHowever if the text was the same size in both orientations, the visual effect would be much more consistent. This where vmin comes into its own. Set the font size using vmin and the size is now set as a proportion of the smallest side of the viewport, giving you a far more consistent rendering.\nh1 {\n font-size: 13vmin;\n}\nLandscape text is consistent with portrait text when using vmin units.\nComparing vw and vmin renderings for various common screen dimensions, you can see how using vmin keeps the text size down to a usable magnitude:\nRendered font size (px)\nViewport\n13\u202fvw\n13\u202fvmin\n320 \u00d7 480\n42\n42\n414 \u00d7 736\n54\n54\n768 \u00d7 1024\n100\n100\n1024 \u00d7 768\n133\n100\n1280 \u00d7 720\n166\n94\n1366 \u00d7 768\n178\n100\n1440 \u00d7 900\n187\n117\n1680 \u00d7 1050\n218\n137\n1920 \u00d7 1080\n250\n140\n2560 \u00d7 1440\n333\n187\n\nHybrid font sizing\nUsing vertical media queries to set text in direct proportion to screen dimensions works well when sizing display text. In can be less desirable when sizing supporting text such as sub-headings, which you may not want to scale upwards at the same rate as the display text. For example, we can size a subheading using vmin so that it starts at 16 px on smaller screens and scales up in the same way as the main heading:\nh1 {\n font-size: 13vmin;\n}\nh2 {\n font-size: 5vmin;\n}\nUsing vmin alone for supporting text can scale it too quickly\nThe balance of display text to supporting text on the phone works well, but the subheading text on the tablet, even though it has been increased in line with the main heading, is starting to feel disproportionately large and a little clumsy. This problem becomes magnified on even bigger screens.\nA solution to this is use a hybrid method of sizing text2. We can use the CSS calc() function to calculate a font size simultaneously based on both rems and viewport units. For example:\nh2 {\n font-size: calc(0.5rem + 2.5vmin);\n}\nFor a 320 px wide screen, the font size will be 16 px, calculated as follows:\n(0.5 \u00d7 16) + (320 \u00d7 0.025) = 8 + 8 = 16px\nFor a 768 px wide screen, the font size will be 27 px:\n(0.5 \u00d7 16) + (768 \u00d7 0.025) = 8 + 19 = 27px\nThis results in a more balanced subheading that doesn\u2019t take emphasis away from the main heading:\n\nTo give you an idea of the effect of using a hybrid approach, here\u2019s a side-by-side comparison of hybrid and viewport text sizing:\ntable.ex--scale{width:100%;overflow: hidden;} table.ex--scale td{vertical-align:baseline;text-align:center;padding:0} tr.ex--scale-key{color:#666} tr.ex--scale-key td{font-size:.875rem;padding:0 0.125em} .ex--scale-2 tr.ex--scale-size{color:#ccc} tr.ex--scale-size td{font-size:1em;line-height:.34em;padding-bottom:.5rem} td.ex--scale-step{color:#000} td.ex--scale-hilite{color:red} .ex--scale-3 tr.ex--scale-size td{line-height:.9em}\n\ntop: calc() hybrid method; bottom: vmin only\n16\n20\n27\n32\n35\n40\n44\n16\n24\n38\n48\n54\n64\n72\n320\n480\n768\n960\n1080\n1280\n1440\n\nOver this festive period, try experiment with the proportion of rem and vmin in your hybrid calculation to see what feels best for your particular setting.\n\n\n\n\nA reference pixel is based on the logical resolution of a device which takes into account double density screens such as Retina displays.\u00a0\u21a9\ufe0e\n\n\nFor even more sophisticated uses of hybrid text sizing see the work of Mike Riethmuller.\u00a0\u21a9\ufe0e", "year": "2016", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2016-12-09T00:00:00+00:00", "url": "https://24ways.org/2016/responsive-display-text/", "topic": "code"} {"rowid": 292, "title": "Watch Your Language!", "contents": "I\u2019m bilingual. My first language is French. I learned English in my early 20s. Learning a new language later in life meant that I was able to observe my thought processes changing over time. It made me realize that some concepts can\u2019t be expressed in some languages, while other languages express these concepts with ease.\nIt also helped me understand the way we label languages. English: business. French: romance. Here\u2019s an example of how words, or the absence thereof, can affect the way we think:\nIn French we love everything. There\u2019s no straightforward way to say we like something, so we just end up loving everything. I love my sisters, I love broccoli, I love programming, I love my partner, I love doing laundry (this is a lie), I love my mom (this is not a lie). I love, I love, I love. It\u2019s no wonder French is considered romantic. When I first learned English I used the word love rather than like because I hadn\u2019t grasped the difference. Needless to say, I\u2019ve scared away plenty of first dates!\nLearning another language made me realize the limitations of my native language and revealed concepts I didn\u2019t know existed. Without the nuances a given language provides, we fail to express what we really think. The absence of words in our vocabulary gets in the way of effectively communicating and considering ideas.\nWhen I lived in Montr\u00e9al, most people in my circle spoke both French and English. I could switch between them when I could more easily express an idea in one language or the other. I liked (or should I say loved?) those conversations. They were meaningful. They were efficient.\n\nI\u2019m quadrilingual. I code in Ruby, HTML/CSS, JavaScript, Python. In the past couple of years I have been lucky enough to write code in these languages at a massive scale. In learning Ruby, much like learning English, I discovered the strengths and limitations of not only the languages I knew but the language I was learning. It taught me to choose the right tool for the job.\nWhen I started working at Shopify, making a change to a view involved copy/pasting HTML and ERB from one view to another. The CSS was roughly structured into modules, but those modules were not responsive to different screen sizes. Our HTML was complete mayhem, and we didn\u2019t consider accessibility. All this made editing views a laborious process.\nGrep. Replace all. Test. Ship it. Repeat.\nThis wasn\u2019t sustainable at Shopify\u2019s scale, so the newly-formed front end team was given two missions:\n\nMake the app responsive (AKA Let\u2019s Make This Thing Responsive ASAP)\nMake the view layer scalable and maintainable (AKA Let\u2019s Build a Pattern Library\u2026 in Ruby)\n\nLet\u2019s make this thing responsive ASAP\nThe year was 2015. The Shopify admin wasn\u2019t mobile friendly. Our browser support was set to IE10. We had the wind in our sails. We wanted to achieve complete responsiveness in the shortest amount of time. Our answer: container queries.\nIt seemed like the obvious decision at the time. We would be able to set rules for each component in isolation and the component would know how to lay itself out on the page regardless of where it was rendered. It would save us a ton of development time since we wouldn\u2019t need to change our markup, it would scale well, and we would achieve complete component autonomy by not having to worry about page layout. By siloing our components, we were going to unlock the ultimate goal of componentization, cutting the tie to external dependencies. We were cool.\nWriting the JavaScript handling container queries was my first contribution to Shopify. It was a satisfying project to work on. We could drop our components in anywhere and they would magically look good. It took us less than a couple weeks to push this to production and make our app mostly responsive.\nBut with time, it became increasingly obvious that this was not as performant as we had hoped. It wasn\u2019t performant at all. Components would jarringly jump around the page before settling in on first paint.\nIt was only when we started using the flex-wrap: wrap CSS property to build new components that we realized we were not using the right language for the job. So we swapped out JavaScript container queries for CSS flex-wrapping. Even though flex wasn\u2019t yet as powerful as we wanted it to be, it was still a good compromise. Our components stayed independent of the window size but took much less time to render. Best of all: they used CSS instead of relying on JavaScript for layout.\nIn other words: we were using the wrong language to express our layout to the browser, when another language could do it much more simply and elegantly.\nLet\u2019s build a pattern library\u2026 in Ruby\nIn order to make our view layer maintainable, we chose to build a comprehensive library of helpers. This library would generate our markup from a single source of truth, allowing us to make changes system-wide, in one place. No. More. Grepping.\nWhen I joined Shopify it was a Rails shop freshly wounded by a JavaScript framework (See: Batman.js). JavaScript was like Voldemort, the language that could not be named. Because of this baggage, the only way for us to build a pattern library that would get buyin from our developers was to use Rails view helpers. And for many reasons using Ruby was the right choice for us. The time spent ramping developers up on the new UI Components would be negligible since the Ruby API felt familiar. The transition would be simple since we didn\u2019t have to introduce any new technology to the stack. The components would be fast since they would be rendered on the server. We had a plan.\nWe put in place a set of Rails tools to make it easy to build components, then wrote a bunch of sweet, sweet components using our shiny new tools. To document our design, content and front end patterns we put together an interactive styleguide to demonstrate how every component works. Our research and development department loved it (and still do)! We continue to roll out new components, and generally the project has been successful, though it has had its drawbacks.\nSince the Shopify admin is mostly made up of a huge number of forms, most of the content is static. For this reason, using server-rendered components didn\u2019t seem like a problem at the time. With new app features increasing the amount of DOM manipulation needed on the client side, our early design decisions mean making requests to the server for each re-paint. This isn\u2019t going to cut it.\nI don\u2019t know the end of this story, because we haven\u2019t written it yet. We\u2019ve been exploring alternatives to our current system to facilitate the rendering of our components on the client, including React, Vue.js, and Web Components, but we haven\u2019t determined the winner yet. Only time (and data gathering) will tell.\nRuby is great but it doesn\u2019t speak the browser\u2019s language efficiently. It was not the right language for the job.\n\nLearning a new spoken language has had an impact on how I write code. It has taught me that you don\u2019t know what you don\u2019t know until you have the language to express it. Understanding the strengths and limitations of any programming language is fundamental to making good design decisions. At the end of the day, you make the best choices with the information you have. But if you still feel like you\u2019re unable to express your thoughts to the fullest with what you know, it might be time to learn a new language.", "year": "2016", "author": "Annie-Claude C\u00f4t\u00e9", "author_slug": "annieclaudecote", "published": "2016-12-10T00:00:00+00:00", "url": "https://24ways.org/2016/watch-your-language/", "topic": "code"} {"rowid": 298, "title": "First Steps in VR", "contents": "The web is all around us. As web folk, it is our responsibility to consider the impact our work can have. Part of this includes thinking about the future; the web changes lives and if we are building the web then we are the ones making decisions that affect people in every corner of the world. I find myself often torn between wanting to make the right decisions, and just wanting to have fun. To fiddle and play. We all know how important it is to sometimes just try ideas, whether they will amount to much or not. \nI think of these two mindsets as production and prototyping, though of course there are lots of overlap and phases in between. I mention this because virtual reality is currently seen as a toy for rich people, and in some ways at the moment it is. But with WebVR we are able to create interesting experiences with a relatively low entry point. I want us to have open minds, play around with things, and then see how we can use the tools we have at our disposal to make things that will help people.\nEvery year we see articles saying it will be the \u201cyear of virtual reality\u201d, that was especially prevalent this year. 2016 has been a year of progress, VR isn\u2019t quite mainstream but with efforts like Playstation VR and Google Cardboard, we are definitely seeing much more of it. This year also saw the consumer editions of the Oculus Rift and HTC Vive. So it does seem to be a good time for an overview of how to get involved with creating virtual reality on the web.\nWebVR is an API for connecting to devices and retrieving continuous data such as the position and orientation. Unlike the Web Audio API and some other APIs, WebVR does not feel like a framework. You use it however you want, taking the data and using it as you wish. To make it easier, there are plenty of resources such as Three.js, A-Frame and ReactVR that help to make the heavy lifting a bit easier.\nGetting Started with A-Frame\nI like taking the opportunity to learn new things whenever I can. So while planning this article I thought that instead of trying to teach WebGL or even Three.js in a way that is approachable for all, I would create my first project using A-Frame and write about that. This is not a tutorial as such, I just want to show how to go about getting involved with VR. The beauty of A-Frame is that it is very similar to web components, you can just write HTML to build worlds that will automatically work on all the different types of devices. It uses WebGL and WebVR but in such a way that it quite drastically reduces the learning curve. That\u2019s not to say you can\u2019t build complex things, you have complete access to write JavaScript and shaders.\nI\u2019m lazy. Whenever I learn a new language or framework I have found that the best way, personally, for me to learn is to have a project and to copy the starting code from someone else. A project lets you have a good idea of what you want to produce and it means you can ignore a lot of the irrelevant documentation, focussing purely on what you need. That reduces the stress of figuring things out. Copying code also makes it easier, because you know your boilerplate code is working. There\u2019s nothing worse than getting stuck before anything actually works the first time. So I tinker. I take code and I modify it, I play around. It\u2019s fun.\nFor this project I wanted to keep things as simple as possible, so I can easily explain it without the classic \u201cdraw a circle then draw an owl\u201d. I wrote a list of requirements, with some stretch goals that you can give a try yourself if you fancy:\n\nMust work on Google Cardboard at a minimum, because of price\nTherefore, it must not rely on having a controller\nAuto-moving around a maze would be a good example\nMove in direction you look\nStretch goal: Scoring, time until you hit a wall or get stuck in maze\nStretch goal: Levels, so the map doesn\u2019t need to be random\nStretch goal: Snow!\n\nI decided to base this project on an example, Platforms, by Don McCurdy who wrote the really useful aframe-extras. Platforms has random 3D blocks that you can jump onto, going up into the sky. So I took his code and reduced it so that the blocks are randomly spread on the ground. \n\n\n
\n \n \n element to mark up |
---|