The feature was supposed to be simple: a form submission that updated user data. However, the frontend developer didnât know the API expecte
Learn how cross-stack pair programming, powered by Extreme Programming (XP), bridges frontend and backend gaps to enhance collaboration and app quality.
If I count my Python experience before a/A, I'm already a polyglot. On the other hand, considering that I can now do more with Ruby after two weeks than I ever did with Python, the standards have been raised. (Although I'm sure I could quickly improve my Python on the back of Ruby should the need arise.)
Today's new language, however, was SQL. Static typing, mysterious "databases," unfamiliar syntax. Weird disagreements on pronunciation. (It's pronounced "sequel" at a/A, with the caveat: "When you get hired by a company, get them to say 'SQL' first, so you can follow their convention. Or risk being mocked to forever and back.")
We spent the day working through SQL Zoo, a series of increasingly complicated database queries. The first half was straighforward (I daresay some of it was trivial!), but it got challenging pretty quickly afterwards, and by day's end we were walking around in circles trying to fit two self-joins with two other self-joins to select all bus routes, and the companies that serviced them, that could take us anywhere that was two buses from "Craiglockhart." Or was it "Sighthill"?
An Uber ride would have saved us a lot of trouble.
Earlier in the day, we saw our last of pure Ruby in Assessment 02. It's incredible to think that we're now capable of building a functioning card game (except for the display, a separate problem) within an hour. With a working, reasonably intelligent AI player, no less.
I also finally encountered a pair-programming challenge today, though it was minor. For the first time, it felt like my partner was picking up the day's material significantly quicker than I was.
I've been pretty well matched so far, but today, at times, it was difficult to keep up. I've learned it's best to stop my partner and say, "I have no idea what this does or why this works. Can you explain it to me?"
The last two weeks have been wonderful---busy and challenging and extraordinarily fulfilling. I'm excited to see where Week 3, and these new multilingual powers, will take me!
On Day 5, Friday, we built minesweeper with the goal of minimizing dependency between the Game and the Board/Tile classes. Exactly what that meant, however, was left for us to decide.
Since we've only been at the this for a week, "dependency" is, at its clearest, still fairly subjective to us, so deciding (to say nothing of agreeing on) what was and wasn't too much coupling was a challenge. For instance, should individual Tile objects on the minesweeper board have any information about their x- and y-positions on the board? If so, are they being initialized with too much information? If not, do we really iterate over every tile each time we want to find a particular one?
I felt, here, that giving a tile information about its position was perfectly reasonable; my partner did not. We were at an impasse, briefly, but Thursday's lecture on effective pair-programming instructed us to give in to reasonable alternate ideas quickly when working in pairs, and to focus on building those ideas as well as possible. The aim, of course, is to write good code while working in teams (as we will out in the real world), not to become attached to, and insist on, a particular method to solve a given problem. (The Ego and Idea classes shouldn't be coupled too tightly, after all!)
I relented this time, just as I'm sure my partner did at others. It certainly felt like I was making more progress today than on any previous day, just in terms of the volume of code we created and understood, regardless of where the ideas originated---or perhaps because we didn't make that distinction. I think I'm getting the hang of this pair-programming thing. I've also been fortunate (though we've all been warned the day will come) to have not yet been paired with someone who is at a significantly higher or lower level than I am.
Tomorrow, we face Assessment 01. The weekend involved lots and lots of practice. So, fingers crossed. Then uncrossed and typing for all they're worth.
Friday ended early with a break from coding: we split up into assigned groups of 8-10 people, broke the ice, and got to know each other as humans rather than blocks of code for the first time, in what will be a Friday tradition with the same group for the remaining eleven weeks. We shared what we were excited about, what we were terrified about, why we're here. The idea is to support each other through the program; it already feels like quite a rite of passage. (Additionally, homework for next week: a group sign or secret handshake. Never mind the assessment, this is important.)
All in all, it's been an absolutely transformative week, and I'm looking forward to the next!
Iâve wanted to work in a pair programming environment, but it was always difficult to justify the lost initial productivity of two programmers working on the same task. When the tasks are numerous and trivial it makes sense to break them up so they can be solved in parallel. Even when an individual task is difficult, Iâve found that it can be even more challenging for two people to see the same solution to a problem. Sometimes the solution to a problem is straightforward once the problem itself is well defined, explaining the problem to another person or rubber ducky can be helpful in fleshing out those undefined details. Â Brainstorming sessions, sanity checks, and intermittent reviews can provide some feedback on the solution and an understanding of the problem. These are great cooperative progress checks to ensure the quality of the final solution without absorbing all of the time of the reviewers in the process.
Senior-junior pairing on the other hand isnât so much about the constant review of the code and the solution as much as the knowledge transfer and relationship building. The mentoring aspect is a much bigger value add than any increased quality of the solution.
For all of my forumulative learning experiences, I never had a close mentor, a senior engineer willing to sit down with me and show me all the details involved in solving more than just an example problem for more than an hour or so. From my perspective, this lack of involvement wasn't a bad thing, I got all of opportunities to try the wrong paths and discover a decent solution the hard way. I had to learn how to learn on my own, and it was tough going. I didn't know what to think of the senior engineers, I had no idea how they did their job better than I did mine. Everyone just bashes their head against this wall of impenetrable code until the code breaks or their head does, right? There were group discussions on tool usage and engineering 'best practices', but not seeing a problem taken from concept stage to production by a senior engineer put a big design block in my way when understanding how problems get solved. The thought process itself was the key to getting things done. While my peers and I would discuss it at length when working on school projects and the like, translating that into the business world was slightly different, as none of us had the experiencing of working at that scope or scale. There's plenty of good advice out there to make the jump, but nothing beats real-world examples.
I've had the chance to coach a few junior engineers so far, and I took the same hands-off approach that was taken with me. I monitored their progress, provided good breakdowns of problems that were easily digestible, and helped when they were stuck. We had some design discussions and some fun bug hunts, but the day to day interaction was generally focused on the high level concepts. The closest I would get to the implementation process would be to provide a some sample code as a starting point or as a test case. I helped proctor a few training sessions that sometimes required intensive interactions, but they were synthetic problems with a solution I already knew. The students never got to see my process of making a solution; I'd watch over their shoulder and ask the how/why questions when I saw something problematic in the code. The philosophy was 'ask, don't tell', everyone was encouraged to have their own creative process. There were technical requirements on the final solution, but not the tools to get there. The debugger was taught, but no one cared if you used printf to do inspection. Any advise given was far too broad to be applicable to a beginner.
I've recently taken a more involved approach, spending a whole week, 8 hours a day, going through each and every step in a new project with an intern. This approach was not taken lightly, it was long build to where I thought this approach was necessary. I found the intern wasn't comfortable at all with learning Python or SQL, the two major tools for this data analysis project. So the pairing was a 'on-the-job training program' as well as an important progression for a auxiliary project. At first I took the same back-seat approach as the training classes, only offering suggestions and not taking control of the problem. Once I saw that the stumbling blocks were all rooted in explaining the problem, I focused on getting a great mutual understanding up front of the general problem and in the specific solution we were after. This was great for the high level project goals, but it quickly became tedious to go back and forth from the whiteboard to the keyboard for the specific tasks, taking a line or block of pseudo-code into something that could be tested. I found that most problems are best explained with concrete examples, something we can both observe and adapt. Because you can't run an algorithm's pseduo-code, writing it out didn't lead to any better understanding of the system if the code itself was an obstacle to understanding. Eventually I found myself in a cycle of explaining, instructing, and exhibiting. We would ask questions back and forth about the problem and what the solution was trying to accomplish. Just explaining the solution to someone helped us both understand all of the assumptions about the problem statement. It exposed how difficult it can be to be critical of how one comes to a solution, not just that the solution works. I often found myself explaining implicit assumptions I had about how the code would work, or what to keep in mind when designing very foundational logic. How would someone who didn't know SQL know how to avoid full table scans when writing queries? You have to be able to justify each and every decision. It stopped me from going down some premature optimizations and it helped the intern understand the requirements and internals of the system. The intern learned equally as many short-cuts about how to avoid unnecessary deeply nested loops with more declarative code, or how important scoping can be to organize thoughts.
I often found that I avoided writing code when mentoring that used advanced features or relied on complex ideas only so that I wouldn't have to explain it. Just because that's how I envisaged the problem doesn't mean that my first instinct is the most understandable solution. This was a big hurdle when explaining my solution to someone who didnât have the same mastery of tools. To them it probably looked like I was skipping steps and prematurely optimizing, instead of starting with something they understood Iâd jump right to what I thought was the juicy parts of the problem, leaving them confused by a solution that wasnât described by terms they understood. My wider vocabulary of solutions doesnât mean that I canât use the simpler pieces, only that I now naturally think with these larger patterns. Instead of thinking about using a loop and an if statement to do something, Iâm thinking about how best to structure the inputs such that I can reduce the complexity of my edge cases. Thereâs a big gap between a developer who thinks âin codeâ and someone who thinks in implementation ideas. I honestly donât think at all if something should be a for loop, a list generator or a map operation. Iâll do some of it out of habit and other parts just feel obvious based on the feel of the solution Iâm pursuing.
When starting from the more basic building blocks, the tendency is to optimize the steps for performance, but leaving a suboptimal solution in terms of performance often opened up additional flexibility when revisiting the algorithm for changes. Enhancements that would have required a large restructuring if the implementation were more efficient were much easier to implement when fewer assumptions were made. I often notice similar productivity gains when comparing my functional and imperative code. Thinking in bigger pieces is tougher up front, each bite of the problem has to be a little bigger in scope than âOk, now we need an if statement to catch this case, and now another function because this is doing something differentâ. This kind of insight and implementation design is super-tough to teach. It isnât a pattern like GoF, itâs a not a technique like TDD, DDD, or AOP, itâs a higher level understanding of the problem to see the lines for more than just the bits. The highest level concepts of programming really require a set of experience that can see how to best leverage all of the tools available to find a solution that best models the problemâs domain.
To return to where this started, what Iâve come to realize is that good mentoring should be tough. Senior developers donât mentor as much as they should (from my experience) and as a senior developer mentoring can be very frustrating because it imposes a big overhead of communication where youâve already completely streamlined your thought process. Having to break down that thought process again appears to be very inefficient. Pairing makes it much, much easier to step through the lines of thinking that are crucial to developing a better understanding of how to solve problems. I used to think that pairing was about the code, itâs quantity, quality, and documentation. But pairing is more about building an understanding of the problem that the code is trying to solve. Bringing two views on the problem can shake out some of the most harmful assumptions that wouldnât have surfaced if a single developerâs vision put something together that âmade sense at the timeâ.
Itâs clear that for pairing to be effective and efficient, there does have to be a good shared vocabulary of techniques and terms. If one developer has a very different take on solutions (even within the same language!) it could be very tough to find a solution that accommodates both. What one programmer thinks is an obvious solution could unintelligible by the other.
Pairing has led to some of my greatest introspective experiences into what I actually do every day. Working in a team doesnât offer the same frequency or types of feedback as working one on one. Itâs the feedback thatâs what really helps grow skills! Iâm looking to do more of this in the future!
How to: How to help a struggling newbie do a better job?
How to: How to help a struggling newbie do a better job?
How to help a struggling newbie do a better job?
I have been the only developer and the de-facto âsenior developerâ on my companyâs flagship product for a while (a .NET WinForms app, but that is not related). Just recently, they brought in a ânewbieâ developer with a fresh computer science degree. No experience with source control, unit testing, software maintenance, etc.
Yesterday was my birthday and a lot has happened here at coding house! We have been working on a new project that will help us track our social media duties per day, and the plan is to use the D3 library to visualize our statistics over time. For the first project we were divided into two teams of three people each but for this project all six of us are collaborating. Â To prepare us for team collaboration, coding house introduced JIRA, a task manager, and we spent a while figuring out how to divide up the tasks and estimate our time to complete each one. Â
To start my birthday off we had yoga in the morning and it felt amazing to get that kind of stretch and strength training in. Â Our instructor has a good balance of hybrid exercises and while they never seem impossible, they definitely require dexterity, strength, and endurance. Â Especially the portion where we do 60 push-ups split between bridges and planks, whew!
Since we have six people working on this project we decided it would be good to pair program tasks and my partner is Aleks, the guy from Denmark. Â We made a lot of progress in the morning but then got stuck on a problem with firebase, a data service we are using for logging in, controlling sessions, and storing our data. Â The problem for us occurred when we were trying to load previous data into our variables. Â The confusion stemmed from firebase's reliance on event based data-reads. Â So, instead of us being able to just say, hey we want data from X table, we have to create a callback function that reads data based when an event occurs. Â The curious part was that our program was working, as long as we didn't redirect the user after they submit their information. Long story short, our script was correct, but we were only triggering it when we clicked on the submit button, and the script needs to occur both when the page loads AND when the user submits their information (to detect if there are any changes in the database). The solution was to copy the portion of the script and paste it into the document.ready function. Â As much as it was frustrating, I can't be mad because little things happen like this in programming all the time, and it requires patience and logical thinking to overcome seemingly trivial bugs like this.
Halfway through this bug the doorbell rang and it was a special delivery for me from my girlfriend! She had found a really good cupcake bakery near our house and ordered strawberry and cookie butter cupcakes. Â They were amazing, I highly recommend cookie butter on anything! We continued to work and finally got to a spot where we were happy, and right after we fixed the bug, dinner was ready! I requested the chef make pad thai as I haven't had thai food since we've been here. Â She seemed hesitant at first because she has never made it, but it was amazing! She really outdid herself, including baking me a cake along with cookies and cream ice cream. We all celebrated by devouring the cake and then playing games the rest of the night. Â All in all a great birthday, but I can't wait to head back to my apartment in the city on sunday and spend time with my girlfriend.
Right now we're watching the USA v Germany world cup match and deciding on what the tasks for the day are. Â I still need to finish my personal website, as well as review some tutorials because we will be having a test over the first two weeks of material this upcoming saturday. Â I'm not worried as I have a pretty good grasp of html5, css, bootstrap, git, javascript/jQuery at this point but I just want to make sure there isn't anything important I've overlooked before we head into the mongodb/node phase. Â Until next time!
jQuery, pair programming, and first meetup while in Coding House
Today I spent nearly all day working on our first project which is a restaurant ordering app. Â We need to get a list of restaurants and their menu items, allow users to select and place an order, and then store the information in localStorage. After that we need to read from the localStorage and somehow render the data.
Initially our instructor said we could just allow users to click a checkbox for an entree item, but we thought it would be more realistic to have a number input field so users could order multiple items. Â I was pair programming with one of my group members, and it was a great experience solving problems collaboratively. Then we thought it would be a cool idea to display the total order amount in real time. Â This choked us up a little bit as if the input field hadn't been clicked on yet it was NaN! We went through a few different solutions that didn't work, but then found some good documentation on NaN. Turns out NaN has some weird quirks. Â For example NaN === NaN would return false! How can something that looks like it should be equal not be equal? Finally we decided to use the method isNan(num) to create an if statement that ignored all empty input fields. Â
I was stuck in the middle of how to parse the whole menu table when we needed to leave for a meetup. Â It's definitely not fun when you're right in the thick of solving a problem and get interrupted. Â Oh well. Â I rode with Nick, the Coding House CEO, and we passed by Facebook HQ which was pretty cool. Â We headed to the Ninefold Meetup which had the speaker Yehuda Katz, a well-known thought-leader in the programming world, who gave a demo of Thor which is based in Ruby. Â Since I haven't studied any Ruby, a lot of the technical demonstration didn't make sense to me due to the syntax, but I was able to follow his logic as he built a quick program that allowed you to see other github user's profiles. Â He also built a quick program that converted an image into ASCII, pretty cool.Â
After the meetup we headed back here and had our daily circle talk about highs and lows for the day, which ended around 10:30. Â We were all pretty tired but Nick encouraged us to get a couple more hours of work done and I'm glad that he did because I returned to my previous problem and was able to figure out a good solution for getting all the relevant data from the user's restaurant order and then I went through a tutorial on localStorage. Â It is actually pretty simple, but obviously shouldn't be used that often due to the low amount of memory that can be allocated. Â What does seem interesting about localStorage though is the possibility to save form fields. Â So, if a user is filling out a really long form with tons of different information and accidentally close their browser or something goes wrong. Â If you have a script autosaving their progress every few seconds, you can make it so users can pick up where they left off. Â This seems like a cool html5 feature that is subtle, but very effective. Â I can't even fathom the amount of times I've hit the back button or accidentally closed out of an order form only to have to re-insert every tiny detail.
Tomorrow we're going to figure out what to do with the data from the user. The other group mentioned something about D3 so I may look into that library to see if there's anything cool we could do with it.