![]() ![]() In case you’re not familiar with singletons, here’s what Wikipedia has to say: It looks like Timecop makes use of the singleton design pattern, which is where that instance variable comes from on line 14. send ( :travel, mock_type, * args, & block ) block_given? val : Time. def freeze ( * args, & block ) send_travel ( :freeze, * args, & block ) end private def send_travel ( mock_type, * args, & block ) val = instance. send_travel method, which looks like this:Ĭlass Timecop include Singleton class << self. Timecop.rb: Defines the Timecop class which contains the. Time_extensions.rb: Monkey-patches Date, Time, and DateTime. Makes it easy to keep track of the time movements on a simple stack.” “A data class for carrying around ‘time movement’ objects. ![]() The comment above the definition of TimeStackItem says: Time_stack_item.rb: Defines the TimeStackItem class. In lib/timecop/ there are three main components: What we’re looking for must be another level deeper.Īh, there we go! We’ve found where all the actual Timecop functionality lives, which brings us to… Isolating components This technique is very standard, and you’ll see it in most gems. The only file in here is lib/timecop.rb, which is responsible for loading the rest of the library, i.e. Most of these files are just gem boilerplate - the meat lies within lib. The first thing I did was to look at Timecop’s file structure. Joe’s mortgage should still be due on line 14, since that line is still running in the context of the freeze. mortgage_due? # false raise 'foo!' end rescue end joe. It allows you to easily manipulate time in your Ruby tests. What’s the most important quality of a code reader? Tenacity! However, most modifications should eventually be introduced in the form of a pull request. You may want to temporarily add a monkey-patch to your project so you can keep working. What chain of method calls leads to the issue site? How can I interrupt, hook, or augment this chain to get what I want? 5) Introduce modification Generally, what part of the code looks like it does the thing I care about? 4) Trace method calls Where does the core functionality live? Which components look like they could help me find answers? Which components are just boilerplate? 3) Identify issue site How are the files organized? How do components (classes, modules, etc) get loaded? 2) Isolate components Personally, I tend to read code the same way each time: 1) Examine the file structure Other examples of goals might be, “I can’t figure out how to do an outer join in Rails,” or, “Why isn’t this Backbone callback getting fired?” How I read code In this post, a bug in Timecop caused one of our scripts to fail, so I needed to read Timecop’s code to find and fix the bug. Generally speaking you won’t go open up one of your app’s dependencies and read it just for fun - you’ll need a goal. Code reading is the process of code exploration. If there’s one message you should take away from this blog post, it’s that reading code is not like reading literature. In this first post, I’ll talk about what it means to “read” code, and then dive into the Timecop gem, a library that’s capable of freezing and travelling through time in Ruby tests. This post is part of what will hopefully become a series of posts about what we discuss during our meetings. At Lumos Labs, we’ve formed a code reading club to celebrate the code we’ve read and tell our co-workers what we learned in the process. In fact, chances are you’re a code reader even if you’re looking back over your own code. Have you ever had to modify a piece of code you didn’t write? Surprise! You’re a code reader too. Have you ever cracked open a misbehaving gem in the hopes of tracking down a bug in your app? If so, then you’re a code reader.
0 Comments
Leave a Reply. |