Wednesday, June 8, 2016

POODR Notes - Chapter 4: Creating Flexible Interfaces

POODR Chapter 4 highlights the importance of the messages that objects send to each other - their public interfaces. Metz points out that when thinking about design it can be easy to get caught up in focusing on Classes, but that it's more useful to direct your focus to the interaction between classes. This helps to reveal responsibilities that may or may not be fulfilled in your project, and in the latter case, can point you in the direction of creating a new object to fill in the gap.

Creating Flexible Interfaces Key Takeaways:
  • Focus on the messages that pass between domain objects
  • Think of a public interface (the public methods of an object) as "a contract that articulates the responsibilities of your class"
  • Focus on what, not how: when objects are interacting with each other, they should know only what they need from the other, but not how their neighbor implements it
  • Design messages to be as context-independent as possible to make them optimally reusable. See the notes on Chapter 3: Managing Dependencies for tips on how to achieve this.
To explore the design of public interfaces, let's revisit the automated library that runs on Ruby. The use case we need to consider is that a user returns a book to the library; when this happens, their account should be updated so that they can rent out another book (increase their allowance), the book should be stored on a shelf, should have its location updated, and should be marked as available for renting.

My first iteration of the design for this feature was taken quite literally from the description above; the user sends a return message to the book, and to the shelf, but right away that feels wrong. It makes sense that book would have a return method in its public interface, but it is beyond the user's responsibility to send that message to book. There is another responsibility - routing the books - that is missing in our domain so far.

Figure 1: User returns a book use case sequence diagram
Figure 1 illustrates an improved design for this feature. We've added the BookRouter class to take on the responsibility of receiving the user's return(book) message, then communicating with Book and Shelf to implement the rest of the behind-the-scenes business logic. Notice that BookRouter asks for what it wants using Shelf's public interface, store, while trusting that Shelf will know how to go about fulfilling its responsibility.

To apply this to your own work, ask these questions when designing interfaces between objects:
  • Does it make sense that this message is in this object's public interface? In other words, does this message describe a core responsibility of the object?
  • Does it make sense for this message to be received by this receiver?
  • Does it make sense for this message to be sent to this receiver from this sender?

Tuesday, March 29, 2016

POODR Notes - Chapter 3: Managing Dependencies


Welcome to the 2nd post in the POODR review series; here, we'll discuss my highlights from Chapter 3: Managing Dependencies. As discussed in the last post, object-oriented programming is about objects and behavior, and the Single Responsibility Principle (SRP) guides us to write objects with their own narrow and clearly delimited scope of data and behavior. In order for the app or program to achieve its mission, it needs those objects to collaborate with each other - this is where managing dependencies comes in, and it is another part of writing classes that are TRUE (Transparent, Reasonable, Useable, and Exemplary).

Identifying Dependencies

Your object has a dependency whenever it has to rely on another object in order to do its own work. To identify these situations, consider whether an object knows the:
  • Name of another class,
  • Name of a message/method it intends to send to someone other than self,
  • Arguments that a message/method requires, or
  • Order of the arguments required.
Each of these kinds of "knowledge" represent a dependency; we call it "managing" dependencies because some reliance on other objects is expected and required, but we don't want it to get out of hand. So if your object knows any of the things in that list, it knows too much, and refactoring requires a harm reduction approach. POODR describes various techniques for managing dependencies and making code as TRUE as possible.

Injecting Dependencies

One way to manage a dependency is to inject it by passing the object in as a parameter. Building the method this way abstracts out references to the type of the object so we can focus on the behavior we are trying to get to, instead of on the kind of thing that can do that behavior. For our examples, we'll continue within the domain of the fully automated library that runs on Ruby.

Here we are writing the signature so that we are passing in an object that responds to length, width, and depth. This makes our code re-useable; if we expand our library collection to include DVDs, our code still works and nothing has to change (except maybe the name of the argument; something like "storable" would work nicely). This way, we are still expecting Shelf to know the name of a message (length) it wants to send to something else, but it's not concerned with what kind of thing that something else is - anything that can respond to that message will work.

Removing Argument-Order Dependencies - WITH RUBY 2.0 UPDATE!!

This technique addresses the 3rd and 4th kind of dependency traps in our list above, and it's pretty straightforward, as Metz describes it, and even more so thanks to updates in Ruby 2.0 and 2.1. In previous versions, the way to get away from argument-order dependencies was to use a hash, which also had the benefit of giving us a way to assign default values, as demonstrated in the example below:

Metz pointed out that even though this adds some verbosity, adding a few extra lines of code for the sake of clarity and reusability is warranted. However, in Ruby versions 2.0 and greater, we can get this functionality for free, thanks to first-class support for keyword arguments. Version 2.1 added in support for required keyword arguments. Read this great post that explains more about Ruby 2+ keyword args, and see the gist below for the updated syntax for our Book initialize method.

Abstracting External Messages with Wrapper Methods

Yet another way to deal with dependencies, especially in cases where we can only change certain parts of the code we are using, is to make them more explicit by abstracting into a wrapper method whatever behavior we are trying to get at - I think of this as leaving a warning sign for the next developer. Metz doesn't talk about this yet, but this will also help with testing; we'll discuss this more in future posts.

This is a bit of a contrived example, but the idea is that we want to compose our methods so that we're relying on messages sent to self as much as possible. In the version of class without a wrapper, buried in the complicated store method is a message sent to book. This is potentially dangerous because it is easy to overlook that external message in a method with a lot of other things going on. In order to be able to focus on just the essential work of the store method, we can abstract out the message sent to book, as we do in the second version of Shelf.

Conclusion

So far, we can sum up what we've learned from POODR this way: TRUE code is a pleasure to work on and relatively inexpensive for the business - this is our aim. If the code is TRUE, a class has one and only one responsibility, and when it must collaborate with other objects, it should know as little as possible about its neighbor in order to get the job done. It may know the name of a message it wants to send to its neighbor, but having to know the order of arguments for that message is asking too much. Using the techniques in this post, we can manage those dependencies and go on blissfully changing our code whenever we get a new requirement.

Tuesday, March 15, 2016

POODR Notes - Chapter 2: Designing Classes with a Single Responsibility

These days, I've been thinking a lot about architecture and design, and I'm revisiting "Practical Object Oriented Design in Ruby." I've read POODR before, many times, but always in bits and pieces, often on the subway. I'd look for insight on a particular point (for example, dependency injection), without reading more about the bigger picture (say, the whole chapter about managing dependencies). So I decided to study smarter by reading whole chapters at a time, underlining and taking margin notes, then going back through to write out (using actual paper!!!) a summary of the main points and what I've learned.

Code needs to be TRUE

This is what I'll be sharing with you, starting with Chapter 2: Designing Classes with a Single Responsibility. This chapter is all about how to organize your code so that it does what you need it to do at the moment and is easy to change and reorganize as you get more information about what the app needs to do. A mnemonic for this idea is that code needs to be TRUE: Transparent about the cost of change, which should be Reasonable relative to the benefit that change would produce, Usable now and in the case of future changes, and Exemplary so that the style and patterns you lay out are worthy of replication as the app grows.

To be the most TRUE, classes should follow the Single Responsibility Principle (SRP), which means it should have one and only one responsibility.  When describing an app, the nouns you use represent classes, as long as they have both data and behavior. As an example, let's say we have a fully automated library that runs on Ruby. A patron comes to the circulation kiosk to identify a book they want to rent and the librarian robot retrieves it from its location in the shelves. Since this is a library, let's start with our Book class.

What is the responsibility of our Book class? As it is now, a book's responsibility is to manage its own properties, like author and title, and to manage its own storage. There are two things in that last sentence that stand out right away. First, if we describe a class's responsibility as "doing this thing" and "doing this other thing," as we just did, there is more than one responsibility. Additionally, a book "storing itself somewhere" doesn't really make sense; a book shouldn't be concerned with its own storage because that is the job of another object, which in our case is Shelf.

Is my class abiding by the SRP?

Now we have two classes: Shelf and Book, each of them abiding by the single responsibility principle. Our code is TRUE: our program does what we need it to do now, and is also organized in a way that will make it easy to change in the future. I'll leave you here with some questions that will help to assess whether a class has one and only one responsibility are:

  • What is the responsibility of this class? If the description includes the word "and" or "or" between two different types of concerns, isolate the different responsibilities in separate classes.
  • Should this domain object be its own class? The answer is yes if it has both data and behavior.
In the next post, we'll look at Chapter 3: Managing Dependencies and how that will help us to write TRUE code. In the comments, share your strategies for making sure your code follows the SRP and how you make it as TRUE as can be.

Friday, March 6, 2015

Programmers == Guardians of the REST

Like so much of programming, HTTP (Hypertext Transfer Protocol) is profoundly simple, yet complex at the same time. In setting up a Sinatra app recently, I found myself getting errors related to how HTTP methods (get, put, post, patch, and delete) really work - and, more precisely, how HTTP really works, so I did some research. Here is what I discovered.

HTTP is a set of standards for sending and receiving messages between independent systems; the client sends a request and the server sends a response. These messages are just a collection of strings - and that is crazy to me! How can a string, which I sometimes think of as the most "lowly" of the data types, have so much power? The power lies in how the string is used - in this case, within the rigidly structured protocol that is HTTP, which dictates that information be passed as strings in a particular format.

Both messages - request and response - have a similar structure, consisting of a header and a body. The content is a series of strings that the browser (in our case) interprets as various kinds of media (text, pictures, audio, etc.). But what is really exchanged is a representation of that media (called a resource in HTTP and REST terms). In this Tuts guide, Ludovico Fisher eloquently explains that "We say that the request and response contain a representation of the resource. By representation, we mean information, in a certain format, about the state of the resource or how that state should be in the future. Both the header and the body [of the message] are pieces of the representation."

Often HTTP is described as an interaction between a client (the requester) and a server (the responder). More wise words from Fisher (see the caption below the picture) alerted me to a nuance in HTTP that I hadn't noticed before. HTTP is not just about the server and the client - there is a third party. It's me! And you, and all the other developers - "guardians of the REST" - out there.

Yesterday, I met Rails and even though I have only seen a tiny bit of what it can do, it's already pretty amazing!! And it would be meaningless (or at least have a VERY different meaning) without the guidance/stability/foundation of HTTP...which itself relies on a series of strings. From the outside, technology can seem divorced from humanity but this revelation about the not-always-mentioned, yet ever-present third party highlights the harmony between man and machine. Strings mean nothing to a computer - that is, until we programmer/guardians give them instructions for how to interpret those characters and assign actions for them.


Remember: it's you, the programmer, who ultimately decides what happens when a certain HTTP method is used. There is nothing inherent to HTTP implementations that will automatically cause resources to be created, listed, deleted, or updated. You must be careful to apply the HTTP protocol correctly and enforce these semantics yourself.
I'm trying to avoid the Spider-Man great power/great responsibility quip....so I'll just allude to it instead! All of this is to say that I am eager to discover more of the potential within this programmer/guardian role and to see what benefits I can bring to technology and humanity through this medium. Happy Friday, fellow guardians!!

Thursday, February 19, 2015

Programming <3 Teamwork <3 Programming

In the past almost-three-weeks of already learning so much about Ruby and programming, I have also been enjoying another subject we have been studying and practicing - teamwork!! Given how we have been operating so far - being seated in groups, switching up those groups periodically, and seeing a reminder on every Ironboard pull request prompt to tag collaborators, it feels like this is as important for us to learn as are the technical aspects of programming. 



Why is it important for us, as beginning programmers, to learn how to develop with a team? Here's what stands out to me the most. There is so much to learn, and many minds are better than one. Already, our programs are getting bigger - they have gone from single files to multiple files and any day I am expecting them to grow more and more. How could one person manage increasingly complex programs? And even if they could, why would they want to? Most of us want to make programming our careers, and even though I have never had a programming job, I am 99% certain that teamwork will be a big part of it. Taking code and systems created by other people, learning the way they have functioned before we got there, and communicating our ideas for how to move the project forward will be essential. There are so many ways to do any one thing, whether it be creating an algorithm to solve a problem or constructing a method within a class, or even variable and method naming conventions. The way people do these things are reflections of how they think, and as a new developer, hearing about other people's thought processes helps me understand both problems and potential solutions better.

So, yes, kumbaya, yay teams, but let's also be real. Working with other people can be really challenging. How do we work as a team?...but also make sure we, as individuals, are learning what we need to learn and getting our Ironboard lights green?! Based on my experience these last 3 weeks (and the previous 30 years of my life), these are my suggestions about how to approach team work.

Give What You Can Offer, Ask For What You Need: At the beginning of the Flatiron day (or, more generally, at the beginning of any project), start off by finding out what everyone's expectations and learning goals are. For example, ask the group, "Is there anything you want to work on together today?" Things move pretty fast around here (and I bet that will happen at a job, too), and from what our instructors have been telling us, it is important to stay together in our learning. That said, people also have to go at their own pace. Checking in about people's expectations - at the beginning of a project, and periodically throughout - is a way to see where everyone is at, and collectively decide on the best course of action from there.

Ask Questions. Also, Tell Me More: I am so fascinated by all the many ways to do things. So far, this is one of my favorite parts of programming. Be curious, ask questions, not just of your wise instructors, but also of your wise classmates. "How did you come up with that solution?" or "Tell me more about the way you did that." are ways to start those conversations, which are actually helpful for both parties, not just the person who is asking the question. When we explain our reasoning, we deepen our understanding and  perhaps it might even reveal connections or decisions we had made that we weren't conscious of while we were programming. Rubber ducking makes us better programmers. 

As perpetual beginners, let's remember:
     A small group of thoughtful people could change the world. Indeed, it's the only thing
     that ever has - Margaret Mead (maybe)

Go team!!!

Wednesday, October 1, 2014

Progress: Moving the needle, sometimes by millimeters, other times by centimeters


Let's talk about progress. The inspiration came from revisiting my first blog post and realizing I needed to update my learning-to-code timeline. Also, I watched this video yesterday:
Maybe it was the "this-is-moving-and-important" music in the background or the earnest tone that made me pay attention. But really, it was just something I needed to hear from an objective source: "Be insatiable...just move the needle in even the smallest way, every day...you are gonna look back and see mountains of movement behind you."Thank you, DevTips!

So let's talk about my progress. Since my first post, I have gotten through a lot more of the Flatiron prework. I have completed the Ruby Codecademy track and the Treehouse Ruby Foundations. I'm still reading Chris Pine's "Learn to Program"....while I learn about Rails. Oh, and I also had an interview for the Flatiron School! I'd ask you to wish me luck, but I'm not going to leave it up to luck. Instead, I'm going to get more insatiable and keep pushing the progress needle. But you can still wish me luck if you want to. I'm not one to turn down a kind word. :-)

Back to progress since the first post. I've been blogging! To you, my blog reader (thanks!), this is obvious, but it is important progress to note. In the first post, I said this would be a technical blog...and it will be. But I'm still learning how to write technically (by reading about it), so stay tuned for more technical content. It's coming, I promise. The needle WILL advance further....hey, look at the next paragraph!!

On top of these things, I have been taking a Girl Develop It Intro to Javascript and jQuery class. Last night was the 3rd of 4 classes. We started class talking about how to interact with the DOM and using the getElementById and get/setAttribute methods. Then we got to the intro to jQuery part and learned the jQuery way to do that. Last night's in-class exercises had us using event handlers and we left off with homework to use JS and jQuery to make a form. Once I submit this blog, I'll be revisiting all of last night's exercises to get some more clarity and depth about these things.

Oh, and one last note on my progress. I edited my first blog post today after I noticed that part of the text had a background-color of white. Not sure how/when that happened - how did I not see it when it was originally published?! I confess I was just using Blogger's WYSIWYG interface with a little bit of html tweaking originally. But I have atoned. First, I checked the HTML for the first post. So many span tags!! The same weird span tags repeated multiple times in one element. Why so many span tags, WYSIWYG, why?!? So I got all of those out of there and fixed some other things and THEN I wrote this post not only directly as HTML, but even in a text editor. Much better!

I'm off to do some event handling. Who knows? Maybe one day all these millimeters and centimeters of progress will add up to many meters, many kilometers of progress!! For the next post, I'll talk about my experience as a newbie going to tech meetups (mostly QueensJS, NYCHTML5, and NYC on Rails) and how that is advancing my progress. In the comments, tell me about progress you've made recently and what keeps you insatiable for more.

Thursday, September 18, 2014

There's a first time for...

...editing and problem-solving within someone else's code. My first time with this was a few days ago!

On a quick visit to my brother and his family, my sister-in-law - I'll call her the client here - asked, "Hey, are you pretty good with HTML?" (Spoiler alert: HTML wasn't really the issue, but yes, yes, I am.)

She needed help with her job's website, which was built and maintained through CMS Made Simple. There was some content she needed to update, and when she tried it herself, she got an error and wasn't sure how to fix it. So that morning, while I wasn't playing with my niece, I was working out this puzzle.


The puzzle

Client's request: Add 1 line of content to 3 different pages of a website
Error: After adding content and trying to submit the changes (which did not include changes to the Name field of this file), an error comes up saying that the Name field is not in the correct format.

So, this seemed like a pretty simple problem. The requirements for the Name field were that they not have spaces or invalid characters; the files, as they had been operating, were named something like "Contact Landing - A," "Contact Landing - B," and "Contact Landing - C." I changed the names* to be in the correct format like so: "ContactLandingA." So that should work, right?

But then, upon saving the changes and refreshing the page, the section within the file disappeared all together. After spending some time trying different things, I decided to take a break and come back to it. And that's when it came to me - of course, since I changed the name of the file, I needed to update the file name wherever it was being referenced.

The next puzzle was to find where it was being referenced. The file I changed was nested within a global content section, and after some investigation, I discovered that it was referenced within a file in the templates directory. The format for referencing the file was one I hadn't seen before and didn't fully understand. I'm not even completely sure what language it was in - maybe PHP? There were curly braces, an "=" and a "$" and some files names, all arranged in a way I didn't quite understand. But I tried some things out, replacing a file name where I thought it made sense - and it worked!!

*Actually, I only changed the name of file A, but left file B as it was so that I would have a comparison - as far as I could tell, there was no version control system here, and I didn't want to break anything. I'm glad I did this - it was helpful as I went along to compare what the code was like before the change, and what the code with the error was. 


The prize

My reward for figuring all this out was, of course, my sister-in-law's thanks, but the best part was how accomplished I felt once I had solved the puzzle!! I have been learning to code for about 3 months now and I'm getting the hang of doing the codecademy.com tutorials, and I've been a little worried about what it would be like to stare down pages of someone- (or ones) else's code and figure out what was going on. With this small, but still sweet, success, I am more confident about jumping into mysterious code. 

Thanks for reading! Tell me about your first experiences working with someone else's code in the comments!