Skip to content

Instantly share code, notes, and snippets.

View paulghaddad's full-sized avatar

Paul Haddad paulghaddad

View GitHub Profile
@paulghaddad
paulghaddad / gist:90f3c0d016587afebc45
Created February 11, 2015 19:00
Level Up 7: Knows why we contribute to Open Source
1. Why do we contribute back to Open Source?
The primary reason we contribute back to Open Source is that the vast majority of the software we use is Open Source. Ruby, Ruby on Rails, Apache, Linux, jQuery, among many other software, are made freely available for use. The second reason we contribute back is to improve the software that we use internally. Open Source projects depend on the community to provide updates, whether this is a security patch or major contribution. Without contributing back, we run the risk that the software won't progress and stay relevant. Finally, it allows individual developers to improve their skills and work on the same code base as some of the world's most experienced developers.
2. What is our policy on Open Source contributions?
There are several important facets to the Enova policy:
- Declaring a project owner who is responsible for the project.
- Adding an MIT license.
- Hosting it on the Enova Github space.
@paulghaddad
paulghaddad / gist:4a0505e8d0062066bfe9
Created February 11, 2015 18:48
Level Up 7: Understands Semver, external APIs and breaking compatibility
1. Explain the situations under which you bump the patch / minor / major version number on your software.
- The Major version number is incremented when API changes will break past versions of the software (1.0.0 -> 2.0.0)
- The minor version number is incremented when functionality is added that does not break past versions of the software or deprecates API functionality. (1.0.0 -> 1.1.0)
- The patch version number is incremented after backwards-compatible bug fixes. (1.1.0 -> 1.1.1)
2. How does that versioning relate to the consumers of your code?
Semantic Versioning communicates your intentions to your code's users of how your change will affect them. They can, in turn, make flexible dependency decisions. For example, Rails depends on the Sprokets gem. If Sprokets increments its version with a major patch, Rails itself can't depend on the new version of Sprockets working. The Gemfile can then specify the range of versions compatible with Rails.
@paulghaddad
paulghaddad / gist:8470e7a16d2b25b06fe9
Created February 11, 2015 18:33
Level Up 7: Understands commitments versus estimates
1. What's the difference between a commitment and an estimate?
An estimate is the ability to place a value on the uncertainty of a future task to the best of one’s current knowledge and assessment. In contrast, a commitment is the promise to deliver or complete a task by a certain date. An estimate is simply a guess when the work can be completed; a commitment includes an estimate but also an explicit deadline when it will be done.
2. How do you communicate the difference in conversation?
When communicating with stakeholders, it is important to be explicit about estimates and commitments. When providing an estimate, you should state, "this is an estimate of how long the task will take, however, our team is not committing to completing it by a certain date." For commitments, stating a date when a task will be completed means it is actually a commitment. It is especially important to be careful in communicating estimates, because they can be interpreted as commitments. The converse, making commitments appea
@paulghaddad
paulghaddad / gist:0546fa8e4f5413aa0476
Last active August 29, 2015 14:15
Level Up 7: Understands DSLs, how to create them, and their limitations
1. Explain why DSLs are an advantage to a language like ruby.
DSLs are by their nature a very expressive and highly readable language that extends Ruby's own expressiveness to a higher level. DSLs not only make a specific task easier, but also make the code clearer. Ruby also lends itself to DSL development because its extensive use of syntactic sugar, including the following language features:
- optional parentheses
- symbols (they are less noisy than strings)
- blocks (enable delayed execution of code)
- literal arrays and hashes
- variable-length arguments
- modules (provide a clean separation of code)
@paulghaddad
paulghaddad / gist:059e714a391b8bbc87c9
Last active August 29, 2015 14:15
Level Up 7: Understands dangerously dynamic code
1. In ruby and rails, we depend heavily on 'magic' behavior. How can we be consistent in our usage of the Principle of Least Surprise and still use this behavior?
In my opinion, using "magic" behavior is consistent with the Principle of Least Surprise if used with commonplace Rails functionality. It is okay to use Rails's magic if the vast majority of Rails programmers are familiar with the usage. For example, defining associations using the Rails syntax (has_many :posts) is not surprising. This syntax is used in most Rails applications, is thoroughly documented and saves developers from writing many methods to make method calls across associations.
2. Show an example of dangerously dynamic code, and one of code that is dynamic but consistent with the other principles you've learned.
An example of dangerously dynamic code is improperly using method_missing to handle calls to methods that don't exist. This provides surprising behavior if the developer is unaware of the use of method_missing. Having the Ruby
@paulghaddad
paulghaddad / gist:e2cccd527e3680879d63
Last active August 29, 2015 14:15
Level Up 7: Considers and guards against error conditions
1. Show some ways that you can make your code more accepting and robust while guarding against errors.
Some of the patterns that make code more accepting and robust, while guarding against errors include:
- Defining conversions to user-defined types. This allows your method to require an input in the form of a class you defined. But, if possible, it will implicitly convert instances of another class to the needed type.
- Use built-in conversion methods, such as Integer or Array, to convert an input into a core type.
- Define conversion functions. This allows you to build a public API that accepts inputs in multiple forms. Internally, you will normalize objects to a single type of your own devising.
- To guard against unworkable input values that can't be converted or adapted into a usable form, it is best to reject them early, using precondition (guard) clauses.
- Use #fetch to assert to presence of a Hash key. This will prevent nil values from occurring when a key is not found in a hash.
@paulghaddad
paulghaddad / gist:e1636a3b363d7e0fc09f
Last active August 29, 2015 14:15
Level Up 7: Knows why prod should be like development, and why it's not
1. Give some examples of problems you've seen (or we see) when dev and prod differ.
The following are some of the issues I have seen when development and production differ:
- The various gems of the application often cause different issues in different environments.
- The application responds differently in production because of the server setup, such as using SSL. Often, this requires configuration changes.
- Because of poor choices in past development, the production database contains poor data, such as improper null values or data that wasn't validated thoroughly. This affects current development decisions because the production data can't be easily modified.
- Using different web servers between environments (i.e., Webbrick in development; Apache or Nginx in production) that are fundamentally different.
2. Explain why dev will never be just like prod, and how we can mitigate some of the differences.
@paulghaddad
paulghaddad / gist:c28e4d00e9a85e46d148
Last active August 29, 2015 14:15
Level Up 7: Doesn't use magic numbers or constants, knows why
1. Explain the problem with the use of magic numbers and constants.
The primary problem with magic numbers and constants is that we don't know their context. We don't know where they come from and their purpose. Furthermore, while the original developer may understand what they mean, in the future, he or other developers will be confused by their meaning. A secondary problem is that magic numbers and constants lead to code duplication. It is easy to continue reusing the same value throughout the code base without ensuring it is DRY.
2. Give an example of the use of 'magic numbers', and suggest a possible refactor.
Original:
class Circle
....
@paulghaddad
paulghaddad / gist:fc074fb656c2da3a824f
Last active August 29, 2015 14:15
Level Up 7: Knows how indices work and the tradeoffs they offer
1. Explain the tradeoff that indices allow us to make.
There is a fundamental tradeoff when using indices. On the positive side, indices allow us to locate and read rows really quickly. On the negative side, indices impose a cost. While indices are a benefit when reading data, they are a detriment when updating or writing data to a table, because they must be maintained. Every single write to a table with an index requires another write to the index table. Moreover, every index will require additional write operations. If there are five indices on a table, an update or insert will require six writes: one to the table itself, and five to update the index tables. This is very inefficient. Thus, the fundamental tradeoff with indices are faster read operations and slower write operations. Indices are a classic example of space-time tradeoffs. We store more data in exchange for fast processing.
2. Show how indices are stored on the filesystem, and explain how that affects the database's ability to use multi-colu
@paulghaddad
paulghaddad / gist:c6821e21a57ff8e4af47
Last active August 29, 2015 14:14
Level Up 7: Employs DRY (and knows when to violate it)
1. Name some techniques we can use to de-duplicate code.
- To remove multiple representations of information, a code generator or filter is often useful.
- Remove duplication between comments and code by eliminating unnecessary comments and writing self-documenting code.
- Since documentation and code representation are two instances of the same knowledge, generate documentation from the code itself (using a tool like RDoc).
- Understand which attributes are mutually dependent on others, and make them calculated. For instance, if a Line class has three attributes, starting_point, ending_point and length, the third is duplicated knowledge. It can be calculated from the first two in a separate method.
- Make it easy to find and reuse components across a system; this allows a team to avoid building them from scratch. Otherwise, different implementations of similar functionality represent duplication of knowledge.
- Refactor using "Extract Method" for duplication in the same class.
- For duplication in views and