grobolom
grobolom
Usual Profundo
48 posts
because why not?
Don't wanna be here? Send us removal request.
grobolom · 3 years ago
Text
Just Get a Job!
In recent years I've seen many tweets like this one: https://twitter.com/alicetweet/status/1562516853473230849
Here’s a novel way to avoid that college “debt trap” - get a job while going to school.
I've found this kind of response frustrating, as I believe it completely ignores the reality of student loan debt and taking a job while in school. As I am a graduate of Rutgers University, I would like to provide an example of how challenging 'getting a job' to cover your student loan debt is. Let's take a look at getting a job at Rutgers New Brunswick, in the hopes of paying for your student loans.
Costs and the Job
First, I'd like to point out a significant barrier - it can be very difficult to find a job as a student. While positions are often open in college areas, competition is steep - there are many students looking for jobs. Anecdotally, my experience was that there were few decently-paying positions open at nearby restaurants at Rutgers. The only easily-available position was a telemarketing/sales position, which paid fairly poorly and did not provide a full-time position. This is still something, but it was the only such job of its kind at Rutgers. Thus, I've chosen to use a barista position in my example, as it is a position that reasonably approximates the kind of salary a student worker could expect.
Based on the Rutgers tuition estimates, the average in-state student needs to pay $30,172 per academic year. Note that this does not include rent / food / etc. for the summer (mid-May until September, ~3 and a half months) or the winter break (short, usually only a few weeks).
Based on some figures, the average incoming student receives only ~$3200 of scholarship aid in their first year. Being generous (and for easier calculations) let us assume that our example student receives $5000 in scholarship aid each year, resulting in a total bill of $25,000 / year that must be covered by loans or pay.
A Barista
According to Indeed.com, the average pay for a Barista in NJ is $10.88 / hour. Let's be generous and round up to $12.00 / hour, which is realistically the most a student would be able to find. Now, again, anecdotally, most baristas do not work a full 40 hours / week. This is quite often the case for students, as they will often not have the necessary availability to cover the full 40 hours. There appears to be plenty of evidence that baristas (and other, similar workers) receive less than 40 hours a week, on top of dealing with extremely inconsistent schedules and stressful work conditions. However, let's assume that, at the very least, each worker will receive 32 hours of work a week for their weeks of employment.
Let's calculate:
weeks of work during school: ~37 weeks
total hours worked at 32/week: 1,184
total paid over this period at $12/hour: $14,208
Uhhh … that's not enough. At a full 40 hours and $13/hour, we're still only at ~$19k for the year. At a full 40 hours per week, at $13 / hour, and a full 50 weeks of work, we reach $26,000 / year. This would cover JUST the ~9 months of school, and does not cover any other common costs:
costs of housing during the off season.
costs of supplies or books, which seems to average around $1300 / year.
travel costs / commuting costs.
Conclusions
There is plenty of evidence that most students graduate with significant student loan debt - and almost a quarter graduate with significant (avg. ~$34,000) private debt, which comes with significantly less borrower protection than federal loan debt. The 'just get a job' response is ignorant of the realities facing students, and even a generous approximation of what such a job would provide in loan relief still indicates that students would leave school with large debts.
In addition, this analysis does not account for other, common situations that students will find themselves in, all of which would result in an even larger gap between their education costs and their ability to pay:
inability to find full-time employment (thus receiving <32 hours/week)
inability to make their ideal salary (thus receiving <$10.88/week)
additional credits / semesters of schooling required
economic downturns resulting in inability to find work
economic reality of the campus area resulting in inability to find work
study / class hour conflicts resulting in reduced employment hours
Tweets like the one at the top are, at best, ignorant of the realities facing students.
1 note · View note
grobolom · 5 years ago
Photo
Tumblr media
Burnout
0 notes
grobolom · 7 years ago
Text
Five Offboarding Tips
Having left my position at Hearst, I was responsbile for tranferring almost two years' worth of knowledge to the tech leads that would replace me in a just a couple short weeks. This was a daunting task, but, while there were some hiccups, I think I was able to do so successfully. It required some forethought and a good place to store and share documentation, but at the end of the day just making sure to care about the process did the most good.
Now that I'm through the process, I'd like to give a few tips as to how you can ensure the same process at your company, be it when you yourself leave or when someone else is getting ready to. Some of these will be tips for outside the actual offboarding process, as ensuring good offboarding means setting up good practices even during less turbulent times.
Have a single docs location that everyone on the team has access to.
Schedule regular knowledge sharing sessions and deep-dives.
Set up a 'Q&A' section that everyone can post to.
Quickly schedule knowledge shares for missing gaps.
Assign an offboarding 'point person'.
1. Have a single docs location
Having a single point where the whole team goes to for documentation is crucial in any organization, not just for the offboarding process. However, it may not be obvious how critical this is until a high-quality contributor leaves. Whatever the situtation, make sure that during this time, you make sure all the documentation related to this person leaving is moved to a single source of truth, and that everyone on the team that is participating in the transition process can easily get to it.
Having this in place will guarantee that everyone stays focused on what is important - leaving behind a consise record of what is known, what is unknown, and where to go from here. Having multiple docs locations, or no clearly assigned spot, means someone may have to spend time reconstructing a web of relationships after the contributor leaves, which wastes time at best, or loses knowledge permanently at worst.
2. Schedule regular knowledge shares and deep-dives
This is another tip that can be implemented immediately, but one of the best ways you can ensure that losing someone doesn't crush your productiviy or kill a team is to regularly schedule knowledge sharing sessions. One of the ways I've seen this happen is to schedule a weekly 'developer chapter' meeting, where engineers are encouraged to talk about and give presentations on work they have done recently on their teams, or even things they have learned or worked on during their spare time.
Keeping well ahead of inevitable team changes is critical. One of the biggest benefits is that doing these sessions ahead of time means that the knowledge tends to be fresh. Scheduling these sessions only at the last minute means a contributor may be trying to remember design decisions or challenging problem solutions at a time when they are being bombarded with hundreds of other questions. It also means that the time spent offboarding can be left for the really tough questions - post-mortem-style questions like 'what would you have done differently on this project' or 'what are the likely upcoming technical hurdles' rather than minutia.
3. Set up a Q&A section in the offboarding docs
One of the better ways to guarantee good knowledge transfer is to ask questions, and keeping those questions public is the best way to keep the flow going. Answering questions in a 'Q&A' format is a good way to both sort through potential gaps in knowledge. It is also less intimidating for newer engineers or those less comfortable publicly asking for some of this information to contribute to the process in a meaningful way. You should periodically sort these questions into sections based on topic so that the end result isn't an unwieldy wall of text, but on the whole even a less sorted list can be helpful.
4. Immediately schedule knowledge shares for missing knowledge
It's most important to rapidly move the person leaving from doing work to moving knowledge to other people. One of the ways you can guarantee a big loss to your company is letting an engineer that is already leaving take all the knowledge they have accumulated, all the bugs they know exist and the tricks they have mastered to get around in your system, and leave without giving any of it away. While there may be important outstanding projects that need to be finished in the timeframe of this person moving on, a focus on getting down what can never be replaced is usually more important than knocking out a few extra tickets.
This is a tip that is also most likely to change as circumstances on the ground change. If there are major feature planning sessions or really important pieces of functionality that are due immediately, it may be more important for this person to finish these tasks than to immediately start writing notes and docs. That said, it's still often the right move to eat the producitivity hit and understand that some things will come in late. It also easier to account for a guaranteed miss on some deliverable than try to eke out a last few hours of work from someone whose productivity may already be on the downswing.
5. Assign a 'point person' for offboarding
The quickest way to get traction on any project is to assign someone to be the main shepherd of that work. Assigning a point person to be the go-to for the off-boarding process is useful for making sure nothing gets missed. It ensures that the teams remaining stay focused on their work and are minimally impacted by the transition process. It also means that the person being offboarded has a consistent line of communication to go through; any questions, issues that arise, or help this person needs to get things in order before leaving can be addressed to a single responsibly party.
Keeping these lines of communications clear is important from both sides. It may be that management has many questions for the person leaving, as do other team leads. Having a dozen interrupting meetings with a variety of concerned workers will make it difficult for the person to focus on sharing their knowledge in a consise and consistent way. They may be distracted and miss important information, or say something verbally that is not written down, but missed later because it was 'already said'.
These tips are only the starting point of making your offboarding process a clean and enjoyable one. They serve to help you keep your relationship with the former employee intact, as well as make sure the company continues chugging along without losing a ton of productive time whenever someone decides to leave. With the tech industry hitting an average attrition rate of 23%, it's important to plan for this inevitability. I hope this leaves you with a good starting point, and gives you some ideas on how to better your own processses.
1 note · View note
grobolom · 7 years ago
Text
Proximity
One of the biggest challenges I've faced since I've moved from being an individual contributor to tech lead has been maintaining my opportunities to work with other senior engineers. My team has undergone significant changes and, as a result, I'm most often the senior member working on any particular feature. While this has had its benefits - mentorship and shared learning through teaching - it's not the same as daily, 1:1 discussions with extremely experienced engineers.
One of the main hurdles to jump in this pursuit is proximity. The floor our teams sit on is split in a very particular way, resulting in some teams sitting quite far away from their coworkers. While engineers still have many other coworkers to reach out to near them, this is enough of a substitute. Getting advice from someone who only vaguely knows what you are working on is very different from seeking the same advice from someone who is handling that code on a daily basis.
Slack is certainly a tool that helps in this respect. It allows you to direct your questions to exactly the developers or team you need advice from. At the same time, the impedance of Slack, like most chat programs, is much greater than that of person-to-person speech. Even on teams that are very comfortable having all manner of difficult and in-depth discussion about the technical topics they work on, this difference is notable. Turning around and asking a teammate's opinion almost always results in a faster, better answer.
The downside to this ease of availability is very real, though. Having teams constantly interrupting each other in their work reduces productivity and leads to frustration and a different form of, most often, self-imposed isolation. However, the trade-offs are worth it, and, with some small adjustments, the negatives can be removed entirely. Pinging someone on Slack before asking them a question in person is good way to guage if they are absorbed into their work or if they have time to discuss. Having obvious indicators of whether or not someone can be interrupted can help: headphones on; a marker; an obvious timer.
The upsides to overcoming these challenges are huge. Gaining insight from a senior developer on something can save hours or days of work. It can pre-empt a long back-and-forth discussion in the later Code Review step. I've been on both the receiving and giving end of both of these many times in the last year. As someone who regularly walks the floor to chat with people, more than once I've stepped at a desk and suggested a refactoring or fix that has saved someone several hours of frustration. I've also interrupted someone from another team for a few seconds in the coffee room and saved days of work from just a nudge in the right direction.
At the end of the day, proximity matters for quality development. Closeness with the engineers that you work with most closely is the primary way you can grow and improve. From the point of view of the company, it also provides enormous benefits in productivity and daily satisfaction. It stimulates growth in developers by allowing them to focus on what matters instead of being mired in minutia. It keeps senior talent from feeling isolated and unable to make the right decisions that keeps the business moving forward. It reduces defects by curtailing implementation problems early in the process. It is absolutely necessary for keeping teams happy and healthy in their work.
0 notes
grobolom · 7 years ago
Text
Learning Focus
One of the parts of meditation that interests me the most is building the skill of observing your thoughts. I find this most interesting because it matches the way many other skills are learned; the idea is not to read something, understanding it, and be able to do it; instead, the process requires you to put yourself in a situation over and over again until the process is automatic rather than something you guide youself into.
This process of observing your own thoughts can be fairly harrowing. As you begin to meditate, you will notice just how chaotic and free your own thought process is. Controlling it will seem both impossible and painful - holding back one's own thoughts and actively focusing on something is very challenging. Unless you have an external focus, this process can be very near impossible. Some thoughts will always pop in, frustrating your meditation.
This is why this process is all about letting the thoughts come and go. It's very important to be gentle with your thought process - being a guide rather than a guardsman is how you can make it through. Slowly shifting your thoughts back when they wander off, but not forcing them to stay in a particular place, allows you to eventually narrow the band of what thoughts come in and out.
And just like any type of learning, this one needs pool-fulls of practice. And, unlike physical skills, there are less obvious markers of success - there's no 'I sunk 15 baskets in a row' or 'I got my mile run down under 7'30"'. Like the creative process, this one is more nebulous. But give it time, and make it regular. Even after a few weeks, you'll find yourself much more focused, and your drifts will come and go more smoothly
0 notes
grobolom · 7 years ago
Text
The Gaming Renaissance
I think the boardgame renaissance is one of the most interesting and positive developments in the gaming world in the last decade. From the mediocre world of Monopoly and Risk come fantastic games like Splendor, Mysterium, or Gloomhaven; games that expand the boundaries of what boards games are; games that push back, hard, against the assumption that gaming has to be a stale, regimented process.
Traditional games have always been a way to bring people together around a table. I can't count the number of people I've met that tell stories about the times they played Monopoly for hours on end. Or the time their Uno session ended with their grandmother flipping over a table. These are funny anecdotes, but today's gaming world is much more than that. Today's board games provide narrative. They provide excitement. They force you to think, to engage, but also to re-evaluate what you think cardboard is capable of.
Take a game like Mysterium, a 2015 game designed by Oleksandr Nevskiy and Oleg Sidorenko. At face value, the game is an advanced version of clue - players are guided towards identifying a murderer, a murder location, and a murder weapon that corresponds to their character in the game. A single player plays the 'ghost', the guide that provides the clues for the other players. At first glance, the game doesn't seem particularly deep; building up the clues using the tarot-esque cards provided to the ghost is fun, but that's about all of it.
However, this game is so much more than that. The clue cards are insanely detailed, abstract pieces of art. The process of getting and giving clues relies not only on the available cards, but also the thoughts and tendencies of your fellow players. Both sides - guessers and clue givers - are forced to dive deep into what parts of which clues apply. They must imagine what the thought process of the person playing each part is, on top of the straight facts of the game.
What's more, the game can be warped and changed in many ways that a simpler game like Clue cannot. Have too many players? Have the 'ghost' be a whole team of players, sharing clue cards and coming up with a plan to distribute them. Warp the game even further by setting 'guessers' on different teams, each with their own 'ghost' - share the clue cards, fight over who gives the better clues and gets their team to the finish fastest. Change the nature of the game entirely and have the 'guessers' give clues to the ghost, each only able to provide a bit of information at a time - guiding the guide instead.
This isn't to say there's no way to 'spice up' some well-known games. There are many 'house rules' around Monopoly, and no less than a dozen ways to mess with Risk. The difference is the scope and ease of adjusting the games of the new era. There is no need to bend over backwards adjusting property prices or messing with dice probability - the tools are all there, ready to use.
Adjustability is only one of the many ways games today push the limits - games like 7th Continent redefine what it means to build a narrative in a game, and games like Gloomhaven replace well-known pastimes like Dungeons and Dragons and replace it with a faster pace, easier rules, and a pre-built story and world. Scythe ignores the limits of more traditional strategy games like Risk and Diplomacy, and games like Coup and One Night Ultimate Werewolf and Resistance solve the problems of older games like Mafia.
There's no better time to get into board games, and no better time to be a long-time fan. Every GenCon brings something new, something bold, something exciting. I can't wait to see what's next.
0 notes
grobolom · 7 years ago
Text
Intent
One of the challenges of designings good system, and writing good code in general, is deciding where and when to draw boundaries. Boundaries can be drawn in many ways - deciding to extract something to a class is a form of boundary drawing, as is extracting a method from a conditional. Modules and microservices are the same - just chalk outlines around a piece of functionality that delineates which parts get to hang out together.
Getting good at figuring out the boundaries is no small task - however, even when you have a sense of the approximate line, there are details that require significant thought. One of these areas is when to remove duplication for the sake of cleaner lines. I'll give an example:
function enterScreen() { if (this.isTop()) { translateFromTop(this.el); return; } translateFromBottom(this.el); } function translateFromTop(el) { el.addClass('bar'); el.doSomeCSSStuff(); } function translateFromBottom(el) { el.addClass('bar'); el.doSomeOtherCSSStuff(); }
Some fairly straightforward code. enterScreen is called at some point by some code, and when doing so, it decides based on some condition whether to call goFromTop or goFromBottom. Now, there is a bit of duplication here - the addClass method is called twice, with the same class. For the sake of a simple argument, let us assume that this class will always be the same.
What should we do here? Is this code good? Well, while the answer to the latter is certainly subjective, there is a case to be made for answering the former with: "let's remove the duplication - remove those methods and do this:"
function enterScreen() { this.foo.addClass('bar'); if (this.isTop()) { el.doSomeCSSStuff(); else { el.doSomeOtherCSSStuff(); } }
Now, this doesn't break any hard 'rules' - we can still easily test this method, and it's short enough that it's clear what's happening. In addition, it saves us some lines - if we have a ton of code, this might save us a decent chunk of bytes, even in the minified code. However, I think this method is a mistake, as it causes a broader, if less obvious problem.
The second code snipper has fuzzier boundaries. In the first snippet, we have drawn a line around our condition - isTop, and made a very declarative statement about what comes after - either we translate something from the bottom, or we translate it from the top. These 'lines' are delineations not only in our code organization, but in our verbiage about what the code expressly does. We are marking, very clearly, what the line around 'translate from the bottom' and 'translate from the top' means. While we are repeating some code, we are clarifying what we consider the boundary - the space between the condition and the code.
In our second snipper, we have made this boundary a bit fuzzier. While we still have an obvious condition - isTop, and it's clear to us what we should do in each case, we don't have a clear understanding of what happens if this code changes. We also don't have a clear understanding as to what is important in this code. We have been told (mostly) that what is important is that we are entering the screen, and that we have a condition - however, the details are not important. In the former case, we are building a fence around each part of that condition, making it clear that we think each piece is separate and important enough to be given its own chalk outline.
This may seem pendantic, but I think it's a decision that, over time, leads to generally better code. While there are certainly areas where you may want to not draw a line around a condition, in my experience most code bases would benefit greatly from that line. All code grows and evolves, but conditionals are where it decays. Drawing thick outlines keeps that decay from spreading - it makes sure that a maintainer of the code is very clear about the intentionality behing the code, not just what's written on the lines.
There are downsides - if you have a large codebase, this could eventually balloon it significantly. If you're not careful, you could end up with a lot of duplication before it's obvious that there are components that are capable of reuse. However, I trust in Sandi Metz's famous mantra - "prefer duplication over the wrong abstraction". It will save your ass in the long run.
0 notes
grobolom · 7 years ago
Text
Creativity and TDD
One of the challenges of creativity in programming is being unable to explore code in a way that one explores other forms of art.
If you are a painter with a blank canvas, you have many ways of playing around with your paint and your brushes and your pallette to form something you've never touched before. You can experiment with changing the angles you use, or painting in a different light, or using a new set of colors or textures. With code, this experimentation sometimes feels out of reach. You can grab a new set of brushes (a new programming language) or a new set of paints (a new type of pattern you've learned) but it's often hard to come up with a new picture. It often feels like you're coloring by number, only varying the colors.
I think test-driven-development is an answer to this challenge of creativity. In particular, London-style TDD is one of the most freeing and though-provoking exercises I've done in programming over the last few years.
Being able to define the forms and shapes of your code before writing it allows you to pull away from pushing blocks of color together and step out into the outline. By outlining the structure of your code first, you can play with what shape it should eventually take. Like molding clay, this shaping allows you to play with what the final product will be before baking anything. It allows you to go far into the absurd with you APIs, describing and defining them without stepping even a bit into the code itself.
This comes with other benefits, as well. By building these shapes and structures ahead of the final product, you can develop more robust code as well. It's easier to see where the snags and challenges will be when you are building the floor those snags will stick out of. It means you can tell when you are doing something wrong, because when writing out the tests you'll be writing code that feels odd, rather than just looks it afterwards.
Now, all of this is not to say that TDD is the solution to all problems of creativity in software. Code requires a large set of tools to be done well, and learning those tools and understanding them in a way that allows you to experiment quickly without getting stuck in the details is no easy ask. But it is possible, and earning the skill needed to do so is rewarding on its own as well.
0 notes
grobolom · 7 years ago
Text
Routine
One of the more interesting parts of a morning routine is how much it resembles its own sort of meditation. As I've started waking up early in the day and going through a more ritualized set of steps, I've found myself feeling the same refreshment and lack of morning mental pressure that I get from meditation.
While I am only now starting to incorporate meditation into my rountine, I've already found pretty big benefits from it. In particular, meditating during my commute has kept me more focused in the morning. It has caused me to keep my mind off of the distractions and frustrations of the commute, something that is very real given the three-quarters of an hour I spend in a tiny space with hundreds of other commuters.
This morning routine has other benefits, though the most striking are the improvements in my day from just the different travel time. Getting to the station at 6 rather than 8 means a few hundred less people to share the train with, as well as a few dozen more empty seats available. Getting off on the right foot each morning is very important to keeping your day feeling good and productive; having to start that day feeling cramped and crowded or having to spend most of it upright, waiting for a transfer is not conducive to these feelings.
The other advantage of the early rise is the lack of general distractions, though this is something other have written about at length and with more eloquent expression. That said, it's important to remind yourself just how many emails, text, and phonecalls you avoid from breaking your flow by just moving to a part of the day where those things don't exist. The vast majority of your coworkers and friends will not be awake with you at 6 am, and even if they are, the last thing they will be thinking off is what to text you.
0 notes
grobolom · 7 years ago
Text
Atmosphere
I have experimented with many apps and tools for reducing distractions and enhancing my meditation, but one of the best by far is Atmosphere by Peak Pocket Studios.
This app is a fairly straightforward white noise generator, but the details and sound quality are what set it apart from many of its competitors. The app allows you to mix and match from around 70 different sounds, even in the free version. It allows volume adjustment by sound type, allowing you to customize your listening experience very closely. It also allows you to import your own sounds, something many competing apps don’t allow you to do.
The sound quality is fantastic, and the sounds loop beautifully. Each sound loop also seems to be asymmetric, resulting in a unique listening experience each time. It avoids the issue that many apps have of having obvious ‘cycles’, which can end up ruining the immersive listening experience.
If you haven’t tried this one out yet, I highly recommend you do. The base app is ad-supported, but at only $2.49 to remove these ads, it’s a must-grab.
0 notes
grobolom · 9 years ago
Text
Simple Python Asyncio
Until recently, I had been struggling to find a good tutorial on Python's asyncio. I was finding that most tutorials handled relatively simple use cases. Either they would demonstrate the use of futures and callbacks as a way of handling asynchronous requests or they would provide an analogue to the usual threading example of splitting up work between a bunch of threads/coroutines. While these are useful examples, my particular use case was different. I needed to communicate between multiple long-running processes, for example something like a chat client.
The Basics
We'll be doing this from the bottom up, so bear with me. Here's our main function in python 3.4+:
# main.py import asyncio from blessed import Terminal def main(): loop = asyncio.get_event_loop() queue = asyncio.Queue() loop.run_until_complete(our_process(queue)) if __name__ == "__main__": main()
Fairly simple. We have an event loop, which is like what a browser silently provides for us when we do front-end javascript. Here, it's explicity, and it will be important for us a bit later when running coroutines. We also have an async queue, which we'll be using to communicate between our different coroutines. The last line of the method tells our loop to run the function our_process until it completes. Let's look at that next.
@asyncio.coroutine def our_process(queue): asyncio.async(something_slow(queue)) asyncio.async(reader(queue)) while True: x = yield from queue.get() print(x)
Less simple, so let's explain. asyncio.async (now asyncio.ensure_future) schedules our two collaborating coroutines. We have a reader, which we'll get to in a minute, and a something_slow method that's going to run a process that takes a long time. This will serve as an example of how execution will jump between these processes.
While above we said loop.run_until_complete, we're going to be looping forever here, since this is our main process, and is what we would normally expect in something like a chat client - loop forever until we send some sort of 'quit' signal. We're going to try to pull items from the queue as soon as they come in and print them. yield from will tell this coroutine to pause here and wait until queue.get() returns data. Seems solid so far. Let's look at our helper coroutines next.
@asyncio.coroutine def something_slow(queue): yield from asyncio.sleep(10) yield from queue.put('something slow is done')
This is fairly simple. We wait 10 seconds and then push a message to the queue. We need the yield from for each because both statements are coroutines themselves, so that's how we pass control to them.
@asyncio.coroutine def reader(queue): while True: loop = asyncio.get_event_loop() future = loop.run_in_executor(None, get_input) key = yield from future if key: yield from queue.put(x)
Here's the main source of our complexity. We've got another long-running coroutine here - our process will switch between this and our_process a bunch as we push things into the queue and read them back. We need the loop because we're going to call run_in_executor, which tells our coroutine to run the get_input function in the 'background'. By default, run_in_executor will run in a separate thread, though we could have it run in a separate process for better performance.
def get_input(): term = Terminal() with term.cbreak(): key = term.inkey(1) if key and not key.is_sequence: return key return None
Here's our last bit, and it's pretty simple. This isn't a coroutine, since we're running it in a separate process using loop.run_in_executor. We're using blessed for it's terminal capabilities, such as nice non-blocking IO and reading single keystrokes.
Review
So let's review for a moment what we've got. We have a two long-running coroutines, our_process and reader, which communicate via an asyncio.queue. They bounce back and forth - whenever one hits a yield from it waits, and the event loop schedules them to run whenever the results of that yield from is ready. One of our coroutines reads from a queue whenever an item is ready and prints it out. The other coroutine runs an input process in the background and pushes the results into the queue.
If you run this code, you should be able to press keys and see them printed to the screen fairly instantly. Also, about ten seconds after running the process, you should see something slow is done appear on the screen. This is our third coroutine waking up after the yield from asyncio.sleep(10) and pushing its own stuff into the queue.
Conclusions
# main.py import asyncio from blessed import Terminal def main(): loop = asyncio.get_event_loop() queue = asyncio.Queue() loop.run_until_complete(our_process(queue)) @asyncio.coroutine def our_process(queue): asyncio.async(something_slow(queue)) asyncio.async(reader(queue)) while True: x = yield from queue.get() print(x) @asyncio.coroutine def something_slow(queue): yield from asyncio.sleep(10) yield from queue.put('something slow is done') @asyncio.coroutine def reader(queue): while True: loop = asyncio.get_event_loop() future = loop.run_in_executor(None, get_input) key = yield from future if key: yield from queue.put(x) def get_input(): term = Terminal() with term.cbreak(): key = term.inkey(1) if key and not key.is_sequence: return key return None if __name__ == "__main__": main()
That's everything. Hopefully that gives you a better illustration of what happens when we have multiple coroutines running in infinite loops, as well as how they communicate. If you need more examples, I highly recommend looking at Mionar's chat client as a similar but more complete example. Also feel free to leave comments or questions below.
0 notes
grobolom · 9 years ago
Text
Track Learning in your Git Commit History
I’m a big fan of building a visual representation of your progress in learning, be it via a Kanban-style set of post-it-notes, a log kept in your notebook, or whatever other method happens to work for me at each moment. However, one of the problems I’ve had is keeping track of things across different media.
This is especially relevant in programming, where I often need to do some learning in addition to writing code. Yesterday, I spent half of my work day reading and watching videos about Python’s asyncio. I then made a bunch of commits to my github projects, which show me a nice visual chart of my commits.
A solution is to keep a repository detailing your learning and notes. As you watch videos or take notes, every hour or half hour you can commit what you have learned to this repository. In this way, your work gets added visually to the git contributions graph.
This is useful for several reason, but the most important for me is that it allows me to better understand (or not worry about) gaps in my commit history. If I’ve spend an entire day reading GOOS, I don’t have to worry that three months down the line I’ll look back and see a completely empty day. It removes the need to keep track of exactly which days you were learning and which you were coding, and as an added bonus it even lets you look through your commit history to see what you were learning each day.
Try it out, and if it works/doesn’t work please leave a comment!
0 notes
grobolom · 9 years ago
Text
Abstract Musings
Lately, I’ve been having a lot of trouble deciding what level of abstraction to choose for my projects. While I’m all in favor of going ‘MVP first all the way’, I’d like to showcase my OO skills while writing this. However, I find it’s very easy (especially at 4 AM) to get bogged down in figuring out which pieces should be unit tested and how and with which collaborators.
I’m not sure there is a good solution to this other than simply more experience writing code. It’s a struggle I hear echoed by many new devs as well, though that does give me some solace in that I am not alone with this problem.
I’ve also noticed this problem occurs much more often when I’m experimenting with new code, especially in new languages. Perhaps my discomfort with a language I don’t know well leads me to revert to only working with what is simple. However, since it leads to shitty code, I’m hoping it goes away quickly.
0 notes
grobolom · 9 years ago
Text
Ego and Stupidity
Today, I experienced a somewhat odd feeling - a competition victory that was not just hollow, but actively frustrating and upsetting.
BJJ competitions can be incredibly intense. Matches bring out the fight-or-flight response often, and competitors have to make rapid decisions; they are trapped in the world of the split-second. While this brings out many positive qualities in people, it also brings out some awful ones, the worst being ego.
Ego led to my opponent’s injury today. While on the longer timeline ego maybe a net zero, today it was a net negative - minus one arm injury and a couple months of training. Ego was the only reason my opponent decided to try to escape a locked-in Kimura submission. It was certainly the reason he kept going despite the initial protest of his arm in the form of crunching, twisting noises that no one should like to hear or feel coming from any internal part of their body.
As I write this, many hours later, I still sit frustrated and upset. I apologized to my opponent of course, as well as his coach, and both assured me not to worry and that ‘these things happen’. Maybe they do. Maybe they shouldn’t.
0 notes
grobolom · 9 years ago
Text
JS Speed Frustration
Perhaps this is more of a fun rant than sheer frustration, but some days JS seems to move too damn fast. I look at tutorials from late in the year 2015 that are already obsolete by January 2016. How the heck is anyone supposed to keep up with a technology that moves faster than they can write about it?
Maybe this is a good thing, though. I’ve yet to see a technology fail because it went ‘too fast’ and if this will be the first then it will at least be an amusing ride. It’s also forcing me and others to stay extra sharp, push a little harder to stay on the bleeding edge. I know it forces me to stay focused while learning and make sure my sources are good, which are important skills to have in your toolbox.
We will see how this all pans out in the near future. If JS is overtaken by some newer language in a couple years or whether it becomes a hulking monolith entrenched forever into our browsers and minds, it will be an interesting ride.
0 notes
grobolom · 9 years ago
Text
CB3-131 GalliumOS Snags
I’m a huge fan of Gallium so far, but when installing it on my new acer I was having some trouble at first.
First, the instructions were not 100% clear on the order that you need to follow to install the new operating system. I reran the install twice by accident, and only then understood that the ‘repeat steps 2-4′ would look exactly the same on both. Luckily, the new documentation is much, much better and covers the issues I was having.
There’s another stick where depending on how you selected your install, keeping the USB drive or stick you have pluggied in on boot will actually prevent you from booting gallium. Apparently there’s a behind-the-secones issue where the process gets stuck in a loop between trying trying to boot from the empty stick.
The next sticking point is wifi + screen brightness. Take a gander at this github issue to see if it’s been fixed, but by default xscreensaver is set to blank the screen on idle. Unfortunately, this kills the wifi and resets your screen brightness to a random preset value. It also doesn’t properly check for idleness, so it actually kills your wifi every few minutes while you're working. Fantastic. Luckily, the solution seems to be simply turning off xscrensaver. Easy.
The final snag is getting the left-alt + up/down to page-up/down. While the default keymap can be selected to have right alt or the search button mapped to the overlay to duplicate this functionality, no matter what is selected the left alt keystrokes are eaten up. To fix this, either install xbindkeys-config via apt-get or simply add the following to your .xbindkeysrc file:
#Page Up "xvkbd -xsendevent -text "\[Prior]"" m:0x8 + c:111 Alt + Up #Page Down "xvkbd -xsendevent -text "\[Next]"" m:0x8 + c:116 Alt + Down
Hope this helps you avoid some of the issues I was having with this install. Otherwise it's been a great productivity boost and I'm happy to be developing locally again!
0 notes
grobolom · 9 years ago
Text
When the Post-Its don’t move
Today was definitely one of those days. Lots of progress but nothing really tangible to show for it. I spend the majority of the day working and then spend a huge amount of time studying and finish the setup of GalliumOS on my chromebook. It was objectively an extremely fruitful day, but subjectively I didn’t feel like I’d really done much. There I was, sitting in the B&N, watching the sun set behind the trees in the distance, Kanban board unchanged except for the single backlog item now pushed into the progress box.
Still, this is not something to get discouraged by, and is one of the reasons I highly recommend keeping a daily journal. A journal that you update regularly so you can build a habit of noting all of the successes and progress you’ve had during the day. It’s also useful to remember that not every day is going to be a huge progress push. Some days are relaxation days. Some days are tougher days. Some days are simply set-up days, much like this one - you invest a little bit extra of your time and it pays big dividends later down the line.
Remember that your goals and the journey to get to them is not a singular step and doesn’t end with one wrong turn. There are plenty of days ahead and plenty of time to make the progress you want.
0 notes