Contract Work

Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Friday, July 22, 2016

Remote Non-Senior Developers, Part 1: What Your Company Should Look For

When I tell developers I meet at conferences or elsewhere that I transitioned from a career in nonprofit management to becoming a software developer I usually get smiles. And then, when I add that since becoming a Dev I've only worked remotely, the smile changes to skepticism. I understand hat skepticism. People have views of what will help a junior Dev be successful, some companies have had bad experiences with non-senior remote developers, and there are lots more stories out there. But as remote work and distributed teams become more prevalent in the field, companies shouldn't feel like they can't hire, train, grow, and mentor less experienced developers as a result. Last month at the United Silver Spring Ruby meet up, I spoke about being a non-senior remote developer (note: non-senior does not explicitly mean junior although I was a remote junior developer). Folks of all experience levels were interested to hear what I had to say because many can't envision what a non-senior remote teammate might look like. Here's s little bit about my experience, what I think makes a successful remote non-senior Dev. Part 1 will cover what a company should look for when considering hiring someone and then part 2 (coming out next week) will go over what a less experienced developer should think critically about before deciding to go remote. 

I won’t lie to you. It does take a special type of person to be a remote worker regardless of their level. This is why some companies decide not to have remote employees at all. And it is a little riskier to hire a remote worker with less experience because do can have a higher risk of not being successful if they are not great (I say great because they do need to be better than good) at the things that make remote workers of any level good remote workers. Here are some characteristics you want to look for when hiring for a remote non-senior developer. 

  1. Someone who takes initiative. There are going to be bumps and issues and as a non-senior dev. In order for the employee to learn and grow as much as they possibly can, they’re going to need to make some decisions, put improvements in place, and get the rest of the team on board with what they need. Make sure that as a company, you look for someone who has done this in the past or has the potential to do this.

  2. Good communication skills. This is necessary for any developer but especially when remote. How can they articulate their thoughts, the research they've done, a problem they're facing, etc. 

  3. Learn about their past. Are they a new professional or just new to development? When I became a developer I had about 7 years of prior professional experience and had already been working from home for 2 years in different industries successfully. I might not be a senior developer technically, but I’ve got all the other skills necessary to be successful.

  4. Make sure the person understands what remote work is all about. Ask them about the best and worst parts of working remotely. I don't like working remotely because I can work in my pjs (which I don't do, for the record). I like it because I have a schedule, more work time without a commute, and a quiet distraction-free workspace. I also have opinions about the parts of working remotely I don't like. I’m aware of all the good parts and bad parts of remote work and I know what i’m getting into when I accept a remote position. You want to ensure you’re hiring someone who also understands these aspects or has at least thought through them.

  5. And maybe most importantly, someone who isn't afraid to say to a slack channel that they are stuck, frustrated, or need help. Without this personality trait, the individual won't be successful because asking questions is probably the most important skill a developer can have.

I find the best way to learn about all of the characteristics above is to ask behavioral interview questions. Instead of the interview where you decide if you'd like to chill with the candidate, ask about scenarios. For example, tell me about when you were stuck on a problem, what did you do? What if no one was available to help you? What was a time you had an issue with a teammate, how did you address it and how was it solved (if at all)? 

Now finding the right candidate is half the battle, but you also want to make sure they’re set up for success. A person isn't an island. They can only exist and thrive if they're put in an atmosphere to do so. Companies sometimes feel they don't have enough resources or structures in place to support a non-senior person but if you have the right candidate, you actually just need a few small things to ensure success.

  1. A good manager who has had some experience/training. This person will be vital for support and working through issues that may come up on the team. They should be an ally and be able to recognize when issues are actually opportunities to help the team as a whole grow and learn more about things like diversity, empathy, mentorship and more. 

  2. A kind, caring team. It is easy as a non-senior Dev to be scared of asking questions but if the team they are put on is supportive, thoughtful, positive, and constructive it will really go a long way in creating an environment with lots of psychological safety where it is easy to learn. 

  3. A system of regular check-ins. It's great if you have a good manager but that manager (or even a tech lead) need to be regularly checking in with this person, especially at the beginning. I think 1-1s are a vital part of a healthy team culture regardless of experience level or if folks are remote, but it’s even more important when you don’t see each other every day in person.

  4. A partially remote team. Even if your current team of remotes are only senior, having a partially remote team means you understand some of the baseline difficulties of remote work regardless of level. It also hopefully means you have some processes in place to allow for easy, async communication and remote pairing tools that are widely used and understood. I'm not saying it won't work if your first remote hire is non-senior but it's definitely going to be a steeper mountain to climb. 


That's it. Really not as involved as you thought it'd be, is it?

Here are the original slides from the talk I gave: https://speakerdeck.com/asheren/remote-non-senior-developers

Stay tuned for Part 2 next week.


And if you’re interested in hiring a remote software developer or want to speak more about the points made here, get in touch!

Sunday, March 6, 2016

Arlington Ruby's Ruby Retrosession 2016

Arlington Ruby RetroSession… Retro ruby for short was this past weekend. I’ve been to retro ruby the past few years, with the exception of last year when I was in labor. It was so fantastic to be back at a community event. I love the unconf idea and feel like I always get a lot out of the conversations so it was great to be able to participate.

The sessions were as follows:

  • Rspec
  • Advanced Newbie (including mentorship, cs without a cs degree, importer syndrome, and ways to step up as an advanced newbie)
  • Freelancing
  • Everything APIs
  • Functional web stacks
  • productivity tools hack
  • infrastructure as code
and
  • making a safe space.


Since this was a 2-track conference, I only went to half of these. There was also ice cream, a retro at the end, and lightning talks.

In addition there was a separate newbie track. Notes and resources gathered from that track are here: https://gist.github.com/kalimar/1a23222b59fd0208f88d

So first I went to the advanced newbie session. We started by talking about mentorship and setting up both formal and informal mentorship opportunities. We never really got into ways to step up, but one CS subject that was mentioned as important for non-cs folks to know was Cryptography and a specific place to do this is through CryptoPals. Another suggestion related to learning cs fundamentals was by watching university courses. A list of these are available through the Github repo awesome courses.

Next I went to everything APIs. The conversation kicked off by asking what do you want the JSON return to look like and how that is a major decision what crafting an API… looking at the response types. I took some notes about things related to APIs that I didn’t know like how api versioning relates to 2 things, the schema and endpoints, where, I think, only the endpoint is usually considered.

There was a great discussion about good practices for external APIs which includes different strategies of putting docs into the actual api. And another discussion about how people like to create APIs… both grape and active model serializers were mentioned.

Some random tools mentioned and things to look up were: Swagger yard was also mentioned as a way to auto-generate documentation. Pact which writes tests in web mock style and then generates a JSON fixture file which gets shared with the micro service where the JSON is generating the response. It then uses a rake task, I think, to execute the tests. This goes along with pact broker which is an intermediate layer. Graphql is really strict about endpoints but generates great docs and is just 1 endpoint… you tell it what object or data structure you want and then it just gives you back only that stuff. Statsd helps you figure out what is still being used which helps with what endpoints are still needed or can be deprecated. I/O docs generates query explorers.

Finally, for API design, someone mentioned tasty pie which is big in the python community and would be great if something similar existed for the ruby community and HATEOAS which is a response call that tells you everything else you can do with your API.

After I bounced between productivity hacks and functional web stacks but spent most of my time in productivity hacks. There’s always great stuff out there. A full-ish list of what was discussed can be found in the hackpad.

The last session I attended was about infrastructure as code. This was really interesting to me because, I feel like one of the next steps for me is to learn more about devops and how deployments, etc. actually work, without the magic of Heroku. The session started out talking about what we think about when we think about infrastructure as code… things like Docker, Ansible, version control, Puppet, and Chef. It is humans changing code and code changing computers. The reason we do this is so that the infrastructure code is repeatable and can be replicated in the future. There are lots of challenges to infrastructure as code but the main thing mentioned was that if you don’t stay up to date on it, then there can be lots of security holes. Additionally, if you want to start learning about thing like Docker, etc. the barrier is pretty high. The tutorials are fairly difficult and since it’s all changing so quickly, lots of information, tutorials, and documentation is out of date.

Some tools mentioned: flynn.io which is a platform as a service. There’s an interface for Docker, push heroku-like commands, and buildpacks. Open shift by Red Hat. Teraform which is a command line utility that can go across services and configure them (i’m not sure this is the best explanation but this is at least a piece of what it does). Otto by Hashicorp which is an opinionated system which seems like it might be a good option for an off-the-shelf solution.

Some good resources to get started include AWS in plain english and twelve factor app which talks a lot about the decisions that need to be made and the things you should be thinking about when you’re looking at infrastructure stuff. Finally, it was suggested that to get started learning about this, to just create a VM on your machine and play around using something like vagrant. And remember, devops is stressful so find a mentor, find a support group, and practice #hugops often.

I didn’t take as many notes on the lightning talks. Someone gave a great talk about note-taking (which I obviously love doing) and suggested to take notes in markdown and to create a notes folder in every repo (or just in your projects folder) and add it to your .gitignore. I actually love this suggestion because recently, I find i’ve got over 10 notebooks filled with notes and without having the time to add color coded tabs to these notebooks, it’s getting more difficult to find things I KNOW I learned so I’ve been debating starting to take these notes in a more searchable fashion (but don’t really want to just have a gazillion notes in evernote) so this sounds like a great suggestion. Also, taking the notes in markdown would force me to become better at it which I think would be super beneficial in general. The other thing I wrote down was a github repo called Dug which provides a more transparent view into open source software and allows you to organize github notifications better than you can with just gmail filters. Also, there were a few talks that related to sleep but I didn’t take notes on any of those because I have an 11 month old. One day I’ll sleep again.

That’s all! Retro Ruby was awesome. It was so much fun to see people again, learn stuff, and have great conversations. Here's the Hackpad with notes from the whole conference.
Plus the t-shirts glow in the dark!!!!

Wednesday, November 18, 2015

RubyConf Australia

I am actually working on a more technical post. It's so difficult to come up with them when I can't show code from work since that's what i'm doing and learning al day!

In the meantime I wanted to announce that I'm SO excited to be speaking at RubyConf Australia in February about working remotely with the phenomenal Kevin Hopkins.

Sunday, October 25, 2015

Look ma, I’m on a podcast!

I talk to people all the time about what it’s like to work remotely, especially what it’s like to work remotely as a newer developer. The wonderful folks at The Frontside decided that it would make a great topic for their podcast this week. Here’s a link:  https://frontsidethepodcast.simplecast.fm/  Enjoy!

Tuesday, March 18, 2014

So Many Random Learnings

I love learning and in the past few weeks, I've learned so much!! In lieu of a more organized post on this stuff, here’s a random smattering of what I’ve learned the last few weeks.

Ls –lM lists everything in list form
Git rebase –i sha is what you use in order to squash commits

Git rebase master… I’m still learning the process and exactly how to troubleshoot this but it seems standard in worksflows that require pull requests and it’s pretty interesting to solve merge conflicts.

Debugging (with capybara): insert a save_and_open_page to see what page/path opens

Alfred workflows are amazing. I’m trying to train myself to use my mouse less. My wonderful mentor suggested that instead of going cold turkey on the mouse, I should start by getting good at just a few things. So, I’m starting with Alfred workflows and trying to get better at not using my mouse within my text editor (sublime).

Alfred workflows that I have set up include spotify, dash, and being able to search for any file or folder on my computer. I’ve got the git workflow partially set up.

In Sublime text, one of the most useful things I’ve learned recently is CMD + . will switch back and forth between the test file and file being tested. CMD T allows you to type to open a file. Just to name a few.
Option and highlight lets you highlight the first letter of each line


Git commit (without –m, etc.) will open your text editor so you can do the commit message there, save it, close it and it’ll bring you back to the command line and finish the commit
Git checkout – brings you back to the last branch you were on
Git rebase –i HEAD ~1 rolls back 1 commit (~2 rolls back 2 commits)

From the command line putting touch and then the path with the filename at the end will create that file

When squashing commits (which means making multiple commits into one commit), you always ‘s’ (squash) the second one

Gem railroady produces a UML diagram of your code structure

Kill process… somehow I created a connection with a server and then I created a second connection with a server and then couldn’t get one of those connections to close!
ps aux | grep finds the process so you can see if it’s running (I’ve since used this ps aux | grep ruby and ps aux | grep puma)
Then kill -9 prodID (number all the way to the left) kills it. Alternatively, you can also kill it by doing killall -9 thin (or whatever you’re trying to kill)

Sunday, March 9, 2014

Final Gem Post- The Action Class

This is a little out of order since it's been a while since my last post on the gem I helped build, but I wanted to get it out there. Feel free to refresh your memory by re-reading these posts 1, 2, and 3. The action class is a small, fairly simple class that is mostly used to just outline all of the attributes in an action item and then also distinguished a few method for specific attributes which are more common or may be requested more often.

The whole class looks like this:
class Action

  attr_reader :attributes

  def initialize(params) 
    @attributes = params
  end

  def title
    @title = attributes['title']
  end

  def description
    @description = attributes['description']
  end

  def reference_name
    @reference_name = attributes['reference_name']
  end

  def action_key
    @action_key = attributes['action_key']
  end
end

The initialize method sets up the class by just creating a hash that is the attributes hash and then the rest of the methods are just pulling out specific pieces from that hash. I’m not sure if by the end of this project, this class will be separate, but to me, it felt like it was doing different stuff than the ActionFetch class so I chose to separate it out.

Saturday, March 8, 2014

Interesting Reads 3/1 - 3/7

A day late is better than a week late. Here are the interesting reads (and watches) from this past week.

Currently, I've been working on a bunch of analytics-related queries and tools. I came across this video about measuring which was really useful.

ember, ember, ember!!: http://www.confreaks.com/videos/2597-lonestarruby2013-ember-on-rails-realtalk

I rewatched this amazing Ben Orenstein talk this past week, refactoring from good to great. I had watched it a few months ago and a lot of the concepts went over my head so it's fun to see how much I've been learning!

Related to the questions I have as a professional programmer, some days are good and some days are bad. This was a great article that helped me realize everyone goes through the same roller coaster.

For Fun.

Beefing up those Comp Sci chops

For anyone who's been asked to FizzBuzz

The Maker's Schedule. An old article but still relevant.

Friday, February 7, 2014

Interesting Reads 2/1 - 2/7

Well, it certainly has been a busy week for me. Fortunately, I've also come across some really interesting articles and things to read/watch. AND I've actually read all of the articles this week (except for the last one... it's a video I haven't had a chance to fully check out yet). There's a variety of stuff in here this week so ...

Enjoy!

Will NOT Work for shoes! I love shoes, but this is a great article about women and their workplace value.

If you've had a rough week or are a newer developer, this short post is a great pick-me-up.

Personally, I'm not very good at celebrating small wins. That, coupled with the fact that I'm getting used to a "dev" to do list, as opposed to a non-dev to do list, makes it hard sometimes to feel like I'm accomplishing greatness. This post talks about that and some great ways to reflect regularly on your work.

Okay, I lied!! I haven't had a chance to read this article about the amazing new Marvel API, but I've gotta find time soon!

On a slightly dryer note... here's some great HTML5 documentation.

In my new position, I'm learning Javascript... lots of Javascript, but Ember.js in particular. Since I'm new to it, I thought this article gave some interesting, basic pointers about the differences between some of the more popular JS languages.

A great post from Aaron based on a question asked at RetroRuby's Newbie track last week!

And to close out this week, here's a video I haven't watched yet about Postgres and things you haven't found.

Monday, February 3, 2014

Getting the Information

In order to actually get the information on the action campaigns that I needed, I needed to use nokogiri to parse the information, create new actions and clients, and then map that information. I started with this code:
# def self.fetch
   #Nokogiri::XML(SalsaLabs::Client.new.request_data('/api/getObjects.sjs', object: 'Action')).css('item').map do |attributes|
   #SalsaLabs::Action.new({title: atributes.css('Title').text)})
   #end
#end
And then used that code to break it into smaller, more transparent methods. I broke the code into five separate methods. First, I created a new class for it called ActionFetch. Then I initialized (or set up) that class setting an instance variable for api_client
def initialize(api_client)
  @api_client = api_client
end
Then, starting from the meat of the class, I created this method:
def data_request
  return @data if @data 
  body = @api_client.fetch('/api/getObjects.sjs', object: 'Action') 
  doc = Nokogiri::XML(body) 
  @data = doc.css('item') 
  @data
end
The data request method starts by saying if there is anything already in the @data instance variable, then just return, if not, then go through the rest of the method’s steps. This is also called Memoizing which basically means storing a value for future use so that you don’t have to run the call over again which saves you time.

The next line says that take the api client (which is the actual http request, set up with faraday, using credentials, etc., set up in a different api client class) and get the stuff that is located at that api endpoint with the params of the object which is named Action. Then, use nokogiri to parse the information that is in the body string (set above). Finally, look at the doc (which is the result of the nokogiri parsing and is now an xml doc) and use the css selector to find all the items. Finally, return the value.

Then, I took those results and fed them into the get_results method.
def get_results
  data_request.map do |attribute_set| 
    new_action(extract_attributes(attribute_set)) 
  end
end
This method takes the results from data_request and for each one (each attribute set), it extracts them into a hash and then makes each of them a new action (it wraps each of the attributes sets in an action class). It does this by using the extract_attributes method which looks like this:
def extract_attributes(action_data)
  action_data.children.inject({}) do |memo, node|
    memo[node.name.downcase] = node.text 
    memo
  end
end
and takes each of the item nodes (action_data is the Nokogiri item tag) and makes them into a hash. And finally, wrapping it in an action class is done by using the new_action method which looks like this:
def new_action(params)
  SalsaLabs::Action.new(params)
end
It just stick each of the params into an object called action which gives the attributes pretty names.
Phew!

Okay, so then, what do I mean by pretty names? Well, in order to see that, I look at the Action class which I’ll cover in the next post.

Wednesday, January 29, 2014

Storing cookies

Once we established the connection with the website and authenticated, we then needed to take the cookie that we got back and save it so that we could call it in the future. I did a bunch of research and looked at a bunch of different options. Quickly, I narrowed it down to a few possibilities. I was considering HTTParty which I had heard good things about and seemed to have good reviews from people about being easy to use and implement. The other option was Faraday which also seems to be pretty popular and was super easy to set up and get running, at least to establish the connection. I also researched an option that included using curl commands in order to save and then reaccess the cookie. There were a few faraday middleware gems that I experimented with but in the end didn’t need to use them. I ended up with this:

@authentication_cookie = response.env[:response_headers]["set-cookie"]

This line finds the header “set-cookie” in the response and sets it to the instance variable.
Then, I wrote this
response = conn.get do |req|
  req.headers['cookie'] = authentication_cookie
  req.url endpoint, params 
end 

return response.body


This code makes another request from the same connection established earlier and sets the header cookies to authentication cookie. It then tells the connection to use a specific endpoint (using the API, based on what information you would like) and adds some parameters. This sets the response to whatever is returned from the api and then response.body takes that response and prints out the content of the response but without the headers or other junk we don’t really want to see.

Saturday, January 25, 2014

Interesting Reads 1/18 - 1/24

This week I started working with Purpose! Working with them this past week has been really interesting and really wonderful... BUT it means that I've currently got close to 80 tabs open covering things from "new stuff to learn" to "things to read" to "things to watch". So... I have definitely not had a chance to read everything on this list yet, but they all seem like excellent pieces for the week.

Enjoy!






Ruby Conferences! (not an article but a new awesome site)

Monday, January 20, 2014

Contributing to OSS

So, if I haven’t said it enough, getting involved in the community is crazy important. I’ve recently been looking for a job. The process has actually been more difficult than I anticipated. A lot of people will tell you it’s incredibly easy to get a job in this field. I’d say that while there are positions available in the field, it is still challenging to convince a company, especially as a newer developer, that you are worth it and that you’ll totally blow them away… if they just give you the chance. Additionally, I want to make sure that where I end up is the right fit. I feel fortunate to have years of professional experience that have allowed me to really know myself as a professional and give me a better ability to determine if a company is a good fit for me or not.

While looking for a permanent position, i’ve been looking for great, challenging projects that continue to expand my skillset and make sure I’m learning as much as possible while I have the time. A few weeks ago, I was approached by a friend at a meetup who had a little too much on his plate and felt he had some work that would provide me with some good experience. Because he’s a friend, he knows my level and therefore I’m very comfortable asking questions. He also thought this project would be a good one because he could provide support, the gem needed to be built but isn’t super crazy complex, and he felt it could provide me with a good opportunity to contribute to OSS… something that is on my goals for this time period and definitely something I’ve been looking to do. Conversely, as a solo freelancer, he hasn’t had the opportunity to often pair or to take part in code reviews, a skill he wants to develop. We saw this as a win-win situation and there I was... working on a ruby gem. The gem posts are a little post-dated because I wrote them as I was working on the gem but didn't have a chance to post everything!!! So, I'll try to get these posts up quickly.

The gem has some simple functionality. It is essentially a way to work with a company’s API and download additional information about email blast campaigns beyond what they currently provide. The gem involves writing tests, utilizing an http client, and working with the API.

I have to admit that a large portion of me is/was terrified. I’m building something new. I’m actually getting paid to do it. AND it’s then going on the interwebs… as a gem… and a part of OSS… for other people to use!!! But fortunately, I’m not terrified enough to shy away from the opportunity.

Geoff had gotten me started by giving me access to a private repo, creating the gem structure, and providing a few details and resources he had thought through in regards to the gem. I started by creating the spec file and thinking through what this gem would do in order to write some tests that could be used essentially as an outline. I put all these tests as pending, but I was able to scope out the major functionalities by thinking about what the output would be and what we would need to make sure is working.

I then started on the actual code. I started by taking the tests and looking at what classes those would create. Classes should each have a single responsibility so I looked at each action that needed to happen and thought about a class structure based on that. My intention is to write the code all in the same file and then do some refactoring to break it up. The next step was looking at the http clients. There is an authentication component to this gem and once the authentication happens, a cookie is received and that cookie needs to be stored in order for it to be used in future actions.

Monday, January 13, 2014

Bot Refactoring

When something is built, it’s never fully done. A application without bugs doesn’t exists and once you release something into the world, there are always issues that come up and ways to make the code better. Releasing the bot into the irc channel brought to the surface a few issues that I’m working on. For example, the bot awards points not just to nicknames but to any word that comes after a number with a + or – symbol in front of it. I’ve also had to change a few regular expressions to make them more specific.

One of the main things I started working on once the initial bot was out was refactoring. Refactoring is important. It’s a way of going back into your code, cleaning it up, making it easier to understand and more transparent. Refactoring also helps to DRY out code, meaning that you look at your code to see when and how you repeat yourself and take out that repetition.

In the bot, there are two main places to refactor based on methods that are called often. For a majority of the functions, I provided an array of responses or gifs as a variable. I then called m.reply variable.sample. So instead of continuing to write this over and over again, I turned these actions into a method.

The method looks like this:
def reply_random(m, list)
  m.reply list.sample
end 
This is pretty easy to read but basically, the list is the array and so the method is to give a random reply based on the list given and replying with a random response from that list.

This is what a corresponding function now looks like:
  on :message, /.*(coffee).*/i do |m|
    reply_random m, [
      "http://wac.9ebf.edgecastcdn.net/809EBF/ec-origin.chicago.barstoolsports.com/files/2012/12/badcoffee.gif",
      "http://thoughtcatalog.files.wordpress.com/2013/08/tumblr_ln3pef2aly1qaq98ro1_400.gif",
     "http://25.media.tumblr.com/57acd60ebc217bc00169fd73b52be5a6/tumblr_mi5u4eeJZv1qcwyxho1_500.gif",
      "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSP8TfZHYrpS1Hz2jM_vdwOToNN949vYDPFZ74G3vw41r4rNH6k",
      "COOOFFFEEEEE!",
    ]
  end

The second method I created to DRY out the code was the second most common functionality. This is where there is an array of response that are either replies or actions and instead of writing out the whole process (as explained in this post about bot functionality) I created an action or reply response method, which operates similarly to the reply_random method above.

def action_or_reply_response(m, list) 
  list = list.sample    
    if list.first == :action     
      m.channel.action list.last 
    else
      m.reply list.last  
    end 
end

and again, with this change, this is what the code looks like:
  on :message, /.*morning.*/ do |m|
     action_or_reply_response m, [
      [:reply, "Good morning to you too!"],
      [:reply, "it's a brand new day!"],
      [:reply, "I'm sleepy today"],
      [:reply, "http://gifrific.com/wp-content/uploads/2012/04/bunny-sleep-work.gif"],
      [:action, "yawns"],
      [:action, "makes coffee"],
      [:action, "*throws open all the windows* it's a glorious day today"]
    ]
  end

Monday, December 30, 2013

Learning: More Tools To Keep You Moving Forward

So, you’ve been working really hard. You are able to check everything below off the list…


  • Involved in the community
  • Setting goals
  • Doing something every day
  • Try ruby
  • Ruby in 100 minutes
  • Read Why’s poignant guide to Ruby
  • Learn Ruby the Hard Way
  • Ruby monk
  • Ruby Rogues (listened to at least a few)
  • Learn to program by Chris Pines


First off, if you were able to cross all those things off the list then seriously, great job!! You’re doing a lot, you’re working your booty off, and hopefully you’re feeling good about it. At this point, you should take a few minutes to take a look back at what you’ve accomplished. Think of everything you’ve learned and everything you didn’t know a few weeks ago. Smile about it, do a mini celebration, and get excited for the rest of your journey.

Here’s the next step… read Practical Object Oriented Programming in Ruby (POODR) by Sandi Metz. It’s amazing and you’ll want to reread it and keep it to refer to in the future. And start watching talks for past conferences. Confreaks is a great site that has talks from all sort of past Ruby conferences. It’s a great way to learn about new things that you might want to look into in the future (or now!). That’s all for now. Read that book carefully to really absorb everything, watch the talks to get inspired, and the next post on learning will be moving on to incorporating Rails!!!

Thursday, December 26, 2013

More Bot Bits

The final component of bot functionality was setting up the database. This was really the thing that I wanted to gain some experience with and by setting up a database not in a rails application, I was able to understand some of the components a bit better. For my purposes, this database would be used to keep track of points. Often times, people will award other people points based on funny or interesting things they post. They’ll also subtract points for things but in the past, we’ve had no way to keep track of this. This bot added the following functionality: adding and subtracting points, telling a user what their score is when they ask, and printing out the leaderboard when asked.

First, Chris and I chose a database. We decided to go with Sequel because it looked pretty interesting and simple to set up. I set up the connection first that created the database but then moved that into a separate file. This way I have the option to run the create table script only when I want to create a new database table. Then I set the database connection as a global constant like this DB = Sequel.connect('sqlite://bot.rb') to get things going and set out to write the related methods.

The first method looks to see if a nickname is already in the database or if we need to add it and acts on that.

def nick_id(nick) 
  set = score.where(:nick => nick) 
  if set.empty?
    nil 
  else
    set.first[:id] 
  end
end

So, we set the variable set which find the list of every score that has the nickname nick (nick being whatever the person’s nickname is). Then, if it doesn’t find anything, then it will return nil. Otherwise, the methods grabs the id of the first matching nick it finds with that name and returns it.

The second method inserts or updates the score.

def insert_or_update_score(nick, points)
  nick.downcase!
  if nick_id(nick)
    row = score.where(:id => nick_id(nick)).first
    updated_points = row[:points] + points      
    score.where(:id => nick_id(nick)).update(:points => updated_points)
  else
    score.insert(:nick => nick, :points => points) 
  end
end

So, first I need to make sure all the nicks are being evaluated in the same way. I discovered this when testing and found that two different nicks would be saved in the database based on if they were capitalized or not. Then, this method needs to fetch a record, then increment the number and then save it back. If there is no nick, then it creates the new nick in the database and gives it points.

Finally, I wanted to be able to lookup the score and if someone has no points then the method throws an exception.

def lookup_score(nick)
  score.filter(:nick => nick).first[:points] 
rescue 
  nil
end

I added a rescue so if there are any exceptions, the rescue catches the exception and returns nil. Chris warned me that when looking at future projects, the rescue option can be dangerous because it can hide serious errors but for our purposes, using rescue is perfectly acceptable.

THEN WE REFACTORED!
Setting the database connection as a global constant is not a good idea and having all of these methods in the main file just make it messy and unorganized. First, I changed the database connection to an instance variable by putting it into a singleton class and initializing it.

require 'singleton'

class DB
  include Singleton
  
  def initialize(file = 'sqlite://bot.db')
    @db = Sequel.connect(file)  #setup the DB connection
  end

This meant that I also had to change all of the DB[:score] instances in the code because it was now @db. Then, instead of just putting @db in each place, I extracted it into a method that does it for us.

def score
  @db[:score]
end

And that is how I set up the bot’s database.

Friday, December 13, 2013

Because it's been a little while... Here's another Euler!

Project Eulers 7 and 8

Just a few more Euler’s left and I realized the other day how long it had been since I’d posted some answers! I’m also posting both 7 and 8 because really, problem 7 uses the prime library again, so the answer is really short and sweet.

So, first, here is the problem:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?


First, here are the tests:

require 'problem7/problem7'

describe 'Prime number positions' do 
  
  it "is the 6th prime number" do 
    expect(Problem7.prime_place(6)).to eq 13
  end

  it "is the 10001st prime number" do
    expect(Problem7.prime_place(10001)).to eq 104743
  end

end

The tests and the code are pretty simple. You’re just using the resources in the prime library and then use the library to list (take) the numbers up until a certain position (ie- the 10,001st position) and then put the last number which is the answer to the question. So, here’s the code:
require 'prime'

module Problem7

        def self.prime_place(position)
          prime_place = Prime.take(position).last
        end

  puts Prime.take(10001).last

end


And now for Euler 8. This problem was actually really tough for me for two reasons… first, it seemed different than most of the others I had done up until now and second, how the heck do you test this thing?!

Here’s the problem:
 Find the greatest product of five consecutive digits in the 1000-digit number.

 73167176531330624919225119674426574742355349194934
 96983520312774506326239578318016984801869478851843
 85861560789112949495459501737958331952853208805511
 12540698747158523863050715693290963295227443043557
 66896648950445244523161731856403098711121722383113
 62229893423380308135336276614282806444486645238749
 30358907296290491560440772390713810515859307960866
 70172427121883998797908792274921901699720888093776
 65727333001053367881220235421809751254540594752243
 52584907711670556013604839586446706324415722155397
 53697817977846174064955149290862569321978468622482
 83972241375657056057490261407972968652414535100474
 82166370484403199890008895243450658541227588666881
 16427171479924442928230863465674813919123162824586
 17866458359124566529476545682848912883142607690042
 24219022671055626321111109370544217506941658960408
 07198403850962455444362981230987879927244284909188
 84580156166097919133875499200524063689912560717606
 05886116467109405077541002256983155200055935729725 
 71636269561882670428252483600823257530420752963450

So, first for the test. After asking around a bit, the best suggestion I got for testing was to break down the string and take 10 or 15 characters and figure out the largest product from that string and then do the same with the larger number.

Here are the tests:
require 'problem8/problem8'

describe 'largest products of consecutive numbers' do 
  it "is the largest product of 5 consective numbers" do 
    expect(Problem8.product(7316717653)).to eq 1764
  end

  it "is the largest product of 5 consecutive numbers" do 
    expect(Problem8.product(7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450)).to eq 40824
  end
end

And so, here’s the solution. First, I created an empty array. Then I wanted to use .each_cons which takes every set of consecutive numbers based on the number of characters you ask for (in this case, it would be 5 because I’m looking for the largest product of 5 consecutive numbers) but .each_cons wouldn’t work because you can’t call .each_cons on a string. So, first, I had to separate the string into individual characters by using each_char. Once the string was separated into each_char (each character) I used the map method to make each of the string characters into an array of integers. Then, I used each_cons(5) which separated the array of integers into arrays of every five characters. The I took the product of each of those integers and pushed it into an array. Finally, the max is called on that array which gives the largest number needed for the answer.
module Problem8
  
  def self.product
    arr = []

    "731671765313306249192251196744265747423553491949349698352"\
    "0312774506326239578318016984801869478851843858615607891129"\
    "4949545950173795833195285320880551112540698747158523863050"\
    "7156932909632952274430435576689664895044524452316173185640"\
    "3098711121722383113622298934233803081353362766142828064444"\
    "8664523874930358907296290491560440772390713810515859307960"\
    "8667017242712188399879790879227492190169972088809377665727"\
    "3330010533678812202354218097512545405947522435258490771167"\
    "0556013604839586446706324415722155397536978179778461740649"\
    "5514929086256932197846862248283972241375657056057490261407"\
    "9729686524145351004748216637048440319989000889524345065854"\
    "1227588666881164271714799244429282308634656748139191231628"\
    "2458617866458359124566529476545682848912883142607690042242"\
    "1902267105562632111110937054421750694165896040807198403850"\
    "9624554443629812309878799272442849091888458015616609791913"\
    "3875499200524063689912560717606058861164671094050775410022"\
    "5698315520005593572972571636269561882670428252483600823257"\
    "530420752963450".each_char.map(&:to_i).each_cons(5) { |a| p arr << a.reduce(:*) }     
    puts arr.max 
  end
end

Phew! Look forward to the last two Eulers, 9 and 10, which I’ll hopefully get to post soon.

Tuesday, December 3, 2013

Mentorship Goals

As many of you know from past posts, I was recently awarded Chris Sexton from the Arlington Ruby group as my mentor. I say awarded because it’s been going really great and I think he’s awesome. I’m so glad Chris is my mentor and we’ve been meeting regularly to make sure I’m learning what I want to. This brings me to my next point, as many of you also know, I think it is very important to set goals. In addition to setting goals for myself so that I can achieve them, goal setting is a vital part of a mentor/mentee relationship. Part of being an effective mentee (I’m going to do a full post about this in the near future) is making it easy for someone to mentor you by being proactive and knowing what you want to learn and accomplish.

One of the first things I did, before chris and I even had a chance to sit down for our first meeting, was let him know what my goals were during this time period. These goals have already changed once or twice and I can always continue to add new goals as we go along, but providing Chris with my goals sets us up for success. I know I’m going to learn a lot and he knows exactly what I want to focus on to learn.

Here are the goals I sent him:
- Pair program at least once per month
- Determine projects to work on (building off of what I have already done and building new things)
- Feel more comfortable with defining my abilities
- Feel comfortable with looking at/thinking about projects that are in progress (not just building rails apps from scratch)
- Learn more about databases and become more comfortable working with them
- Determine how to set good programming goals (there's so much to learn, how do you determine what gets you to the next level and how to get there)
- Commit to OSS

I’ve already started my first project with him of building a bot! The bot is going to be awesome and we’re going to incorporate some information that needs to go into a database in order for me to really get a better sense of working with databases, how they work, and what problems might arise when using them. I’ll definitely be doing some posts soon on the process of building a bot.

Sunday, December 1, 2013

Learning… The next few tutorials and tools

My apologies for not posting for a few weeks on this topic! I imagine that those of you who followed the last post on tools to get started with have completed those three resources and are very ready to move on.

Next on the list is learn ruby the hard way. This tutorial is great and you can get it free, online. I recommend working through it. This will take you a while and probably, at some point in the middle, you will lose steam and not want to do the rest of the lessons. BUT continue and push through it. Take notes. Do ALL the extra credit. Keep all your exercises in a folder. It gives you a really solid step by step guide to ruby that is a little more advanced than the last group of links I provided. It also provided me with a lot of good questions to ask more seasoned developers to get more information on how certain things worked or what certain things were.

If you’d like to simultaneously be reading a book while doing this, I recommend Chris Pines "Learn to program". To be honest, I didn’t read this book but have since skimmed through most of it. This will give you a good foundational background in programming. Now, this is the stuff that may get tedious and may seem boring (I know I had a really difficult time keeping motivated and focused through this part.) It is so annoying when you just want to build cool things but you just don’t know enough yet to build awesomeness. Don’t worry, the awesomeness is coming!!! But you’ve gotta make it through this first.

Next, do Ruby Monk. I did Ruby Monk way too late, but once I did it, it clarified a lot of definitions and parts of Ruby for me once I did it.

Additionally, start listening to podcasts and figuring out which resources you like. I really enjoy Ruby Rogues, especially their picks at the end but there are a lot of different podcasts, both free and for a low-cost.

Finally, I wanted to toss out two additional resources that aren’t necessarily tutorials. This is an awesome resource: http://iwanttolearnruby.com. It lists a lot of different tutorials and resources, notes the level and cost (if any). It’s a good place to find a lot of the resources I’ve mentioned and more. And last, this article came out this week and I thought it was a really great read with some good messages and thoughts to keep in mind about what she wishes people had told her when she started learning to code. https://medium.com/learning-to-code/565fc9dcb329

Keep going!!

Tuesday, November 26, 2013

Are you good code or bad code? - Day 3, Session 4

This was the last session of the conference but fortunately, also one of the most fun sessions! The session was moderated by Matt Aimonetti and featured a panel discussed if bad ruby code exists. The panel was comprise of Aaron Patterson, Bryan Liles, and Bryan Helmkamp. If you have a chance, WATCH THIS TALK! As opposed to being a presentation, it was actually a really interesting discussion. I have a few notes from this session that I’ll write below but a lot of the conversation was mostly about questions to ask yourself as a developer when you’re writing code. Additionally, the panel members talked about their perspectives on good code, bad code, get it done code, etc. Overall, they were all really good points for me to continue to keep in mind as I work on different projects and in the future, work on more complicated projects.

First, there was a discussion about what is good code. The consensus seemed to be that good code was more testable, more maintainable, and more extendable. Most people seemed to settle on the fact that there is no bad code, but there definitely is code and better code. To this point, Bryan from Code Climate talked about the static analysis of code which helps people make more informed decisions. He hopes that the code climate process is helping to make better coders and also help determine what is better code.

Second, there was some discussion of “the rules”. I found this really interesting since I’m still learning the rules and the rules are important. When you’re first learning, it’s important to know the best practices and what the rules are. The goal is to get to a point where you can decide in an educated way if you want to break that rule or group of rules and why.

A question came up about refactoring and when you should take the time to look over your code, refactor and make those changes. The panel discussed always asking themselves the question of “how long would it take me to take this code and make it easier/better?” (easier/better meaning easier to work with or in). When the answer is around a week or longer, you’ve probably gone too far without pausing to refactor.

One suggestion based on this is when you’re working in a class, decompose the things into composed methods. In other words, factor out methods into smaller methods.

But seriously, watch this talk. It was entertaining, humorous, interesting and I feel like made me a better developer in a very different way than most of the other sessions.

The most important things I took from this talk:
1. Good development is knowing why versus how
2. A good developer knows the rules and also knows when to break them
3. Write the best code you can in the time you have
4. Focus on moving forward. Be a better developer today than you were yesterday, be better this year than you were last year, and so on.