Forked from dbc-challenges/0.3.2-readable_code_original_gist.rb
Last active
August 29, 2015 13:56
-
-
Save carolineartz/950923fb8c4b02aaf577 to your computer and use it in GitHub Desktop.
As a programmer, you should always strive to make your code as readable as possible. In this challenge, we'll focus on the hallmarks of good readable code and refactor a previous challenge using some guidelines.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Readable Code Refactoring Challenge | |
| # ----------------------------------- | |
| # Goals of readable code | |
| # 1. Elimination of repetition, using looping and branching wisely | |
| # 2. Complex operations are decomposed into constituent parts | |
| # 3. Descriptive names for methods, variables, classes, and modules | |
| # 4. Methods are small and behavior is obvious | |
| # 5. Minimizes need for comments because the code tells you what it is doing | |
| # 6. Code is formatted with proper indentation for optimal readability | |
| # My original code: | |
| # ----------------- | |
| class CreditCard | |
| def initialize(card_number) | |
| raise ArgumentError.new("Invalid card length.") if card_number.to_s.length != 16 | |
| @card_number = card_number | |
| end | |
| def check_card | |
| validate = @card_number.to_s.reverse.gsub!(/(\d)(\d)/){|match| $1 + ($2.to_i*2).to_s} | |
| validate.chars.map(&:to_i).reduce(:+) % 10 == 0 | |
| end | |
| end | |
| # Refactoring Notes: | |
| # ------------------ | |
| # * Splitting into two classes => better reflect real world object relationships | |
| # | |
| # * Validation class => After splitting it made more sense IMO to decompose/clarify validation | |
| # => Naming the validation class identifies applied algorithm | |
| # | |
| # * Valiadtion class methods => Decompose complex operations from original check_card method; | |
| # resutls in methods of mroe obvious behavior | |
| # => (Re)named variables and methods to be more descriptive | |
| # Code refactored for readability: | |
| # -------------------------------- | |
| class CreditCard | |
| attr_reader :card_number | |
| def initialize(card_number) | |
| @card_number = card_number | |
| end | |
| def check_card | |
| (LuhnValidator.new(@card_number)).is_valid? | |
| end | |
| end | |
| class LuhnValidator | |
| def initialize(card_number) | |
| raise ArgumentError, 'Invalid card length.' if card_number.to_s.length != 16 | |
| @card_string = card_number.to_s | |
| end | |
| def double_digits(number_as_string) | |
| number_as_string.reverse.gsub(/(\d)(\d)/) do |match| | |
| $1 + ($2.to_i*2).to_s | |
| end | |
| end | |
| def summed_digits | |
| double_digits(@card_string).chars.map(&:to_i).reduce(:+) | |
| end | |
| def is_valid? | |
| summed_digits.modulo(10) == 0 | |
| end | |
| end | |
| # Review and Reflect: | |
| # ------------------- | |
| # I'm curious to see how other people completed this assignment. For me, it is often difficult to | |
| # remember that the least amount of code does not equal clear and concise code. That said, I was | |
| # still surprised at how significant the discrepency in length between the old and new versions. I | |
| # hope to find out if this is on the right track for refactoring, I definitely find the process | |
| # difficult and sometimes counter-intuitive. I referenced a textbook I have on refactoring in | |
| # addition to the resources provided and found it helpful. I will definitely be taking some time to | |
| # review my fellow boots' solutions for this challenge if we're given the opportunity! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment