Last active
July 25, 2025 06:53
-
-
Save kwhandy/b2fcfad4db468d8b4a4448344be0cde0 to your computer and use it in GitHub Desktop.
understand ruby from business background
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
| # Computer Science Concepts for Business People | |
| # Using Trading, Business, and Monopoly Analogies in Ruby | |
| puts "=" * 60 | |
| puts "PART 1: BASIC DATA STRUCTURES" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 1. ARRAYS - Like a Filing Cabinet | |
| # ========================================== | |
| puts "\n1. ARRAYS - Your Company's Filing Cabinet" | |
| puts "-" * 40 | |
| # Think of an array as a filing cabinet with numbered drawers | |
| # Each drawer (index) holds exactly one document (value) | |
| # You can access any drawer directly if you know its number | |
| company_departments = ["Sales", "Marketing", "Finance", "HR", "IT"] | |
| puts "Our company departments (array):" | |
| company_departments.each_with_index do |dept, index| | |
| puts " Drawer #{index}: #{dept}" | |
| end | |
| # Adding a new department (like hiring a new division) | |
| company_departments << "Legal" | |
| puts "\nAfter adding Legal department: #{company_departments}" | |
| # Accessing specific department (like going to drawer #2) | |
| puts "Department in drawer 2: #{company_departments[2]}" | |
| # Business analogy: Arrays are like employee ID systems | |
| # Employee ID 0 = First employee, ID 1 = Second employee, etc. | |
| employee_salaries = [50000, 60000, 75000, 80000, 90000] | |
| puts "Employee #2's salary: $#{employee_salaries[2]}" | |
| # ========================================== | |
| # 2. LINKED LISTS - Like a Supply Chain | |
| # ========================================== | |
| puts "\n2. LINKED LISTS - Your Supply Chain Network" | |
| puts "-" * 40 | |
| # A linked list is like a supply chain where each supplier | |
| # knows only about the next supplier in the chain | |
| class Supplier | |
| attr_accessor :company_name, :next_supplier | |
| def initialize(name) | |
| @company_name = name | |
| @next_supplier = nil | |
| end | |
| end | |
| # Creating our supply chain | |
| raw_materials = Supplier.new("Raw Materials Co") | |
| manufacturer = Supplier.new("Manufacturing Inc") | |
| distributor = Supplier.new("Distribution LLC") | |
| retailer = Supplier.new("Retail Store") | |
| # Linking the chain (each supplier points to the next) | |
| raw_materials.next_supplier = manufacturer | |
| manufacturer.next_supplier = distributor | |
| distributor.next_supplier = retailer | |
| puts "Supply chain flow:" | |
| current = raw_materials | |
| while current | |
| puts " #{current.company_name}" | |
| if current.next_supplier | |
| puts " ↓ (ships to)" | |
| end | |
| current = current.next_supplier | |
| end | |
| # ========================================== | |
| # 3. STACKS - Like a Stack of Invoices | |
| # ========================================== | |
| puts "\n3. STACKS - Your Invoice Processing Stack" | |
| puts "-" * 40 | |
| # A stack works like a pile of invoices on your desk | |
| # Last invoice you put on top is the first one you process (LIFO) | |
| invoice_stack = [] | |
| # Adding invoices (pushing onto stack) | |
| puts "Adding invoices to process:" | |
| ["Invoice #001", "Invoice #002", "Invoice #003"].each do |invoice| | |
| invoice_stack.push(invoice) | |
| puts " Added: #{invoice} (stack: #{invoice_stack})" | |
| end | |
| # Processing invoices (popping from stack) | |
| puts "\nProcessing invoices (most recent first):" | |
| while !invoice_stack.empty? | |
| current_invoice = invoice_stack.pop | |
| puts " Processing: #{current_invoice}" | |
| end | |
| # Real business example: Undo functionality in software | |
| action_history = [] | |
| action_history.push("Created report") | |
| action_history.push("Added chart") | |
| action_history.push("Changed colors") | |
| puts "\nUndo last action: #{action_history.pop}" | |
| puts "Remaining actions: #{action_history}" | |
| # ========================================== | |
| # 4. QUEUES - Like Customer Service Line | |
| # ========================================== | |
| puts "\n4. QUEUES - Your Customer Service Line" | |
| puts "-" * 40 | |
| # A queue is like a customer service line | |
| # First customer in line gets served first (FIFO) | |
| customer_queue = [] | |
| # Customers joining the line (enqueue) | |
| puts "Customers joining the service line:" | |
| ["Alice", "Bob", "Charlie", "Diana"].each do |customer| | |
| customer_queue.push(customer) # Add to back of line | |
| puts " #{customer} joined the line (queue: #{customer_queue})" | |
| end | |
| # Serving customers (dequeue) | |
| puts "\nServing customers (first come, first served):" | |
| while !customer_queue.empty? | |
| current_customer = customer_queue.shift # Remove from front of line | |
| puts " Now serving: #{current_customer}" | |
| puts " Remaining in line: #{customer_queue}" | |
| end | |
| puts "=" * 60 | |
| puts "PART 2: ADVANCED DATA STRUCTURES" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 5. TREES - Like Company Organization Chart | |
| # ========================================== | |
| puts "\n5. TREES - Your Company's Organization Chart" | |
| puts "-" * 40 | |
| # A tree is like your company's org chart | |
| # CEO at top, managers below, employees under managers | |
| class Employee | |
| attr_accessor :name, :position, :subordinates | |
| def initialize(name, position) | |
| @name = name | |
| @position = position | |
| @subordinates = [] | |
| end | |
| def add_subordinate(employee) | |
| @subordinates << employee | |
| end | |
| # Show org chart (tree traversal) | |
| def show_hierarchy(level = 0) | |
| indent = " " * level | |
| puts "#{indent}#{@name} (#{@position})" | |
| @subordinates.each { |sub| sub.show_hierarchy(level + 1) } | |
| end | |
| end | |
| # Building the company tree | |
| ceo = Employee.new("Sarah", "CEO") | |
| sales_manager = Employee.new("John", "Sales Manager") | |
| tech_manager = Employee.new("Mike", "Tech Manager") | |
| # Adding managers under CEO | |
| ceo.add_subordinate(sales_manager) | |
| ceo.add_subordinate(tech_manager) | |
| # Adding employees under managers | |
| sales_manager.add_subordinate(Employee.new("Alice", "Sales Rep")) | |
| sales_manager.add_subordinate(Employee.new("Bob", "Sales Rep")) | |
| tech_manager.add_subordinate(Employee.new("Carol", "Developer")) | |
| tech_manager.add_subordinate(Employee.new("Dave", "Developer")) | |
| puts "Company Organization Chart:" | |
| ceo.show_hierarchy | |
| # ========================================== | |
| # 6. GRAPHS - Like Trading Networks | |
| # ========================================== | |
| puts "\n6. GRAPHS - Your Trading Network" | |
| puts "-" * 40 | |
| # A graph is like a trading network where companies | |
| # can trade with multiple other companies (not just hierarchical) | |
| class TradingNetwork | |
| def initialize | |
| @connections = {} # Hash to store trading relationships | |
| end | |
| def add_company(company) | |
| @connections[company] = [] unless @connections[company] | |
| end | |
| def add_trading_relationship(company1, company2) | |
| add_company(company1) | |
| add_company(company2) | |
| @connections[company1] << company2 | |
| @connections[company2] << company1 # Bidirectional trading | |
| end | |
| def show_network | |
| puts "Trading Network Connections:" | |
| @connections.each do |company, partners| | |
| puts " #{company} trades with: #{partners.join(', ')}" | |
| end | |
| end | |
| def find_trading_path(start, destination, visited = []) | |
| return [start] if start == destination | |
| return nil if visited.include?(start) | |
| visited << start | |
| @connections[start].each do |partner| | |
| path = find_trading_path(partner, destination, visited.dup) | |
| return [start] + path if path | |
| end | |
| nil | |
| end | |
| end | |
| network = TradingNetwork.new | |
| network.add_trading_relationship("Apple Corp", "Google Inc") | |
| network.add_trading_relationship("Apple Corp", "Microsoft Ltd") | |
| network.add_trading_relationship("Google Inc", "Amazon Co") | |
| network.add_trading_relationship("Microsoft Ltd", "Amazon Co") | |
| network.show_network | |
| # Finding if Apple can reach Amazon through trading partners | |
| path = network.find_trading_path("Apple Corp", "Amazon Co") | |
| puts "\nPath from Apple Corp to Amazon Co: #{path.join(' → ')}" | |
| # ========================================== | |
| # 7. HASHING - Like Employee ID System | |
| # ========================================== | |
| puts "\n7. HASHING - Your Employee ID System" | |
| puts "-" * 40 | |
| # Hash tables are like employee badge systems | |
| # Each employee gets a unique ID that quickly finds their info | |
| class EmployeeDatabase | |
| def initialize | |
| @employees = {} # Hash table for O(1) lookup | |
| end | |
| def add_employee(id, name, salary) | |
| @employees[id] = { name: name, salary: salary } | |
| puts "Added employee: #{name} with ID #{id}" | |
| end | |
| def find_employee(id) | |
| employee = @employees[id] | |
| if employee | |
| puts "Found: #{employee[:name]}, Salary: $#{employee[:salary]}" | |
| employee | |
| else | |
| puts "Employee with ID #{id} not found" | |
| nil | |
| end | |
| end | |
| def update_salary(id, new_salary) | |
| if @employees[id] | |
| old_salary = @employees[id][:salary] | |
| @employees[id][:salary] = new_salary | |
| puts "Updated #{@employees[id][:name]}'s salary from $#{old_salary} to $#{new_salary}" | |
| end | |
| end | |
| end | |
| # Using our employee database | |
| hr_system = EmployeeDatabase.new | |
| hr_system.add_employee("EMP001", "Alice Johnson", 65000) | |
| hr_system.add_employee("EMP002", "Bob Smith", 70000) | |
| hr_system.add_employee("EMP003", "Carol Davis", 75000) | |
| puts "\nLooking up employees:" | |
| hr_system.find_employee("EMP002") | |
| hr_system.find_employee("EMP999") # Not found | |
| hr_system.update_salary("EMP001", 68000) | |
| # ========================================== | |
| # 8. HEAPS - Like Priority Customer Service | |
| # ========================================== | |
| puts "\n8. HEAPS - Your VIP Customer Service System" | |
| puts "-" * 40 | |
| # A heap is like a VIP customer service system | |
| # Highest priority customers get served first, regardless of arrival time | |
| class VIPCustomerService | |
| def initialize | |
| @customers = [] # Array to represent heap | |
| end | |
| def add_customer(name, priority) | |
| # Add customer with priority (higher number = higher priority) | |
| @customers << { name: name, priority: priority } | |
| bubble_up(@customers.length - 1) | |
| puts "Added #{name} with priority #{priority}" | |
| end | |
| def serve_next_customer | |
| return nil if @customers.empty? | |
| # Serve highest priority customer (root of heap) | |
| customer = @customers[0] | |
| # Move last customer to root and bubble down | |
| @customers[0] = @customers.last | |
| @customers.pop | |
| bubble_down(0) unless @customers.empty? | |
| puts "Now serving: #{customer[:name]} (Priority: #{customer[:priority]})" | |
| customer | |
| end | |
| private | |
| def bubble_up(index) | |
| return if index == 0 | |
| parent_index = (index - 1) / 2 | |
| if @customers[index][:priority] > @customers[parent_index][:priority] | |
| @customers[index], @customers[parent_index] = @customers[parent_index], @customers[index] | |
| bubble_up(parent_index) | |
| end | |
| end | |
| def bubble_down(index) | |
| left_child = 2 * index + 1 | |
| right_child = 2 * index + 2 | |
| largest = index | |
| if left_child < @customers.length && @customers[left_child][:priority] > @customers[largest][:priority] | |
| largest = left_child | |
| end | |
| if right_child < @customers.length && @customers[right_child][:priority] > @customers[largest][:priority] | |
| largest = right_child | |
| end | |
| if largest != index | |
| @customers[index], @customers[largest] = @customers[largest], @customers[index] | |
| bubble_down(largest) | |
| end | |
| end | |
| end | |
| vip_service = VIPCustomerService.new | |
| vip_service.add_customer("Regular Customer", 1) | |
| vip_service.add_customer("Gold Member", 5) | |
| vip_service.add_customer("Diamond VIP", 10) | |
| vip_service.add_customer("Silver Member", 3) | |
| puts "\nServing customers by priority:" | |
| 4.times { vip_service.serve_next_customer } | |
| puts "=" * 60 | |
| puts "PART 3: DYNAMIC PROGRAMMING" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 9. DYNAMIC PROGRAMMING - Like Investment Planning | |
| # ========================================== | |
| puts "\n9. DYNAMIC PROGRAMMING - Smart Investment Planning" | |
| puts "-" * 40 | |
| # Dynamic Programming is like smart investment planning | |
| # Instead of recalculating the same scenarios repeatedly, | |
| # we remember (memoize) the results of our calculations | |
| class InvestmentPlanner | |
| def initialize | |
| @memo = {} # Our memory bank for calculated results | |
| end | |
| # Classic DP problem: Fibonacci sequence for compound interest | |
| # How much money after n years with compound growth? | |
| def compound_growth(years, growth_rate = 1.1) | |
| # Base cases | |
| return 1000 if years == 0 # Initial investment | |
| return 1100 if years == 1 # After 1 year | |
| # Check if we already calculated this | |
| key = "#{years}_#{growth_rate}" | |
| return @memo[key] if @memo[key] | |
| # Calculate and store result | |
| result = compound_growth(years - 1, growth_rate) * growth_rate | |
| @memo[key] = result | |
| puts "Year #{years}: $#{result.round(2)} (calculated and stored)" | |
| result | |
| end | |
| # Knapsack problem: Maximum profit investment portfolio | |
| def best_investment_portfolio(investments, max_budget) | |
| # investments = [{name: "Stock A", cost: 1000, return: 1200}, ...] | |
| # Create a table to store maximum returns for each budget | |
| dp = Array.new(max_budget + 1, 0) | |
| investments.each_with_index do |investment, i| | |
| cost = investment[:cost] | |
| profit = investment[:return] - investment[:cost] | |
| # Work backwards to avoid using same investment twice | |
| (max_budget).downto(cost) do |budget| | |
| if dp[budget - cost] + profit > dp[budget] | |
| dp[budget] = dp[budget - cost] + profit | |
| puts "With budget $#{budget}, best return is $#{dp[budget]} profit" | |
| end | |
| end | |
| end | |
| dp[max_budget] | |
| end | |
| end | |
| planner = InvestmentPlanner.new | |
| puts "Calculating compound growth over 5 years:" | |
| final_amount = planner.compound_growth(5) | |
| puts "Final amount after 5 years: $#{final_amount.round(2)}" | |
| puts "\nFinding best investment portfolio:" | |
| investments = [ | |
| { name: "Tech Stock", cost: 2000, return: 2800 }, | |
| { name: "Real Estate", cost: 3000, return: 4000 }, | |
| { name: "Bonds", cost: 1000, return: 1300 }, | |
| { name: "Crypto", cost: 1500, return: 2200 } | |
| ] | |
| max_profit = planner.best_investment_portfolio(investments, 5000) | |
| puts "Maximum profit with $5000 budget: $#{max_profit}" | |
| puts "=" * 60 | |
| puts "PART 4: SORTING & SEARCHING ALGORITHMS" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 10. SORTING ALGORITHMS - Like Organizing Sales Data | |
| # ========================================== | |
| puts "\n10. SORTING - Organizing Your Sales Reports" | |
| puts "-" * 40 | |
| class SalesAnalyzer | |
| # Bubble Sort - Like organizing papers by repeatedly swapping | |
| def bubble_sort_sales(sales_data) | |
| puts "Bubble Sort: Organizing sales like sorting papers on desk" | |
| data = sales_data.dup | |
| n = data.length | |
| (n - 1).times do |i| | |
| swapped = false | |
| (n - i - 1).times do |j| | |
| if data[j] > data[j + 1] | |
| data[j], data[j + 1] = data[j + 1], data[j] | |
| swapped = true | |
| puts " Swapped: #{data[j + 1]} and #{data[j]} → #{data}" | |
| end | |
| end | |
| break unless swapped | |
| end | |
| data | |
| end | |
| # Quick Sort - Like organizing by dividing into groups | |
| def quick_sort_sales(sales_data) | |
| puts "Quick Sort: Divide sales into groups around a pivot" | |
| return sales_data if sales_data.length <= 1 | |
| pivot = sales_data[sales_data.length / 2] | |
| puts " Using pivot: #{pivot}" | |
| left = sales_data.select { |x| x < pivot } | |
| middle = sales_data.select { |x| x == pivot } | |
| right = sales_data.select { |x| x > pivot } | |
| puts " Left (< #{pivot}): #{left}" | |
| puts " Middle (= #{pivot}): #{middle}" | |
| puts " Right (> #{pivot}): #{right}" | |
| quick_sort_sales(left) + middle + quick_sort_sales(right) | |
| end | |
| # Merge Sort - Like merging sorted department reports | |
| def merge_sort_sales(sales_data) | |
| return sales_data if sales_data.length <= 1 | |
| mid = sales_data.length / 2 | |
| left = merge_sort_sales(sales_data[0...mid]) | |
| right = merge_sort_sales(sales_data[mid..-1]) | |
| merge(left, right) | |
| end | |
| private | |
| def merge(left, right) | |
| result = [] | |
| i = j = 0 | |
| # Merge like combining two sorted reports into one | |
| while i < left.length && j < right.length | |
| if left[i] <= right[j] | |
| result << left[i] | |
| i += 1 | |
| else | |
| result << right[j] | |
| j += 1 | |
| end | |
| end | |
| # Add remaining elements | |
| result + left[i..-1] + right[j..-1] | |
| end | |
| end | |
| # Testing sorting algorithms | |
| monthly_sales = [15000, 8000, 23000, 12000, 31000, 9000, 18000] | |
| analyzer = SalesAnalyzer.new | |
| puts "Original sales data: #{monthly_sales}" | |
| puts "\nBubble Sort Results:" | |
| bubble_result = analyzer.bubble_sort_sales(monthly_sales) | |
| puts "Sorted: #{bubble_result}" | |
| puts "\nQuick Sort Results:" | |
| quick_result = analyzer.quick_sort_sales(monthly_sales) | |
| puts "Sorted: #{quick_result}" | |
| puts "\nMerge Sort Results:" | |
| merge_result = analyzer.merge_sort_sales(monthly_sales) | |
| puts "Sorted: #{merge_result}" | |
| # ========================================== | |
| # 11. SEARCHING ALGORITHMS - Like Finding Customer Records | |
| # ========================================== | |
| puts "\n11. SEARCHING - Finding Customer Records" | |
| puts "-" * 40 | |
| class CustomerSearch | |
| def initialize(customer_list) | |
| @customers = customer_list.sort # Binary search needs sorted data | |
| end | |
| # Linear Search - Like looking through files one by one | |
| def linear_search(target) | |
| puts "Linear Search: Checking each customer one by one" | |
| @customers.each_with_index do |customer, index| | |
| puts " Checking position #{index}: #{customer}" | |
| if customer == target | |
| puts " Found #{target} at position #{index}!" | |
| return index | |
| end | |
| end | |
| puts " #{target} not found in customer list" | |
| -1 | |
| end | |
| # Binary Search - Like using phone book strategy | |
| def binary_search(target) | |
| puts "Binary Search: Using divide-and-conquer like a phone book" | |
| left = 0 | |
| right = @customers.length - 1 | |
| while left <= right | |
| mid = (left + right) / 2 | |
| puts " Checking middle position #{mid}: #{@customers[mid]}" | |
| if @customers[mid] == target | |
| puts " Found #{target} at position #{mid}!" | |
| return mid | |
| elsif @customers[mid] < target | |
| puts " #{target} is larger, searching right half" | |
| left = mid + 1 | |
| else | |
| puts " #{target} is smaller, searching left half" | |
| right = mid - 1 | |
| end | |
| end | |
| puts " #{target} not found in customer list" | |
| -1 | |
| end | |
| end | |
| # Testing search algorithms | |
| customer_names = ["Alice Corp", "Beta Industries", "Charlie Ltd", "Delta Inc", | |
| "Echo Systems", "Foxtrot Co", "Golf Enterprises"] | |
| searcher = CustomerSearch.new(customer_names) | |
| puts "Customer database: #{searcher.instance_variable_get(:@customers)}" | |
| puts "\nSearching for 'Delta Inc':" | |
| searcher.linear_search("Delta Inc") | |
| puts "\nBinary search for 'Delta Inc':" | |
| searcher.binary_search("Delta Inc") | |
| puts "=" * 60 | |
| puts "PART 5: COMPLEXITY ANALYSIS (BIG O)" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 12. BIG O NOTATION - Like Business Efficiency Analysis | |
| # ========================================== | |
| puts "\n12. BIG O - Measuring Business Process Efficiency" | |
| puts "-" * 40 | |
| class EfficiencyAnalyzer | |
| # O(1) - Constant Time: Like accessing employee by ID badge | |
| def constant_time_example(employee_database, employee_id) | |
| puts "O(1) - Constant Time: Direct employee lookup by ID" | |
| puts " No matter if we have 10 or 10,000 employees," | |
| puts " finding by ID always takes the same time" | |
| start_time = Time.now | |
| employee = employee_database[employee_id] | |
| end_time = Time.now | |
| puts " Found employee in #{(end_time - start_time) * 1000} milliseconds" | |
| employee | |
| end | |
| # O(n) - Linear Time: Like counting all inventory items | |
| def linear_time_example(inventory_list) | |
| puts "O(n) - Linear Time: Counting total inventory value" | |
| puts " Time grows proportionally with inventory size" | |
| start_time = Time.now | |
| total_value = 0 | |
| inventory_list.each_with_index do |item, index| | |
| total_value += item[:value] | |
| puts " Item #{index + 1}: $#{item[:value]} (Running total: $#{total_value})" | |
| end | |
| end_time = Time.now | |
| puts " Processed #{inventory_list.length} items in #{(end_time - start_time) * 1000} milliseconds" | |
| total_value | |
| end | |
| # O(n²) - Quadratic Time: Like comparing every employee with every other | |
| def quadratic_time_example(employee_salaries) | |
| puts "O(n²) - Quadratic Time: Finding all salary comparison pairs" | |
| puts " Time grows exponentially - very slow for large datasets!" | |
| start_time = Time.now | |
| comparisons = 0 | |
| employee_salaries.each_with_index do |salary1, i| | |
| employee_salaries.each_with_index do |salary2, j| | |
| next if i >= j # Avoid duplicate comparisons | |
| comparisons += 1 | |
| if salary1 > salary2 | |
| puts " Employee #{i} ($#{salary1}) earns more than Employee #{j} ($#{salary2})" | |
| end | |
| end | |
| end | |
| end_time = Time.now | |
| puts " Made #{comparisons} comparisons in #{(end_time - start_time) * 1000} milliseconds" | |
| puts " With #{employee_salaries.length} employees, we needed #{comparisons} comparisons" | |
| puts " Formula: n(n-1)/2 where n = #{employee_salaries.length}" | |
| end | |
| # O(log n) - Logarithmic Time: Like binary search in sorted customer list | |
| def logarithmic_time_example(sorted_customers, target) | |
| puts "O(log n) - Logarithmic Time: Binary search efficiency" | |
| puts " Even with millions of customers, only needs ~20 steps!" | |
| start_time = Time.now | |
| steps = 0 | |
| left, right = 0, sorted_customers.length - 1 | |
| while left <= right | |
| steps += 1 | |
| mid = (left + right) / 2 | |
| puts " Step #{steps}: Checking position #{mid} (#{sorted_customers[mid]})" | |
| if sorted_customers[mid] == target | |
| end_time = Time.now | |
| puts " Found #{target} in #{steps} steps!" | |
| puts " Time taken: #{(end_time - start_time) * 1000} milliseconds" | |
| return mid | |
| elsif sorted_customers[mid] < target | |
| left = mid + 1 | |
| else | |
| right = mid - 1 | |
| end | |
| end | |
| end_time = Time.now | |
| puts " #{target} not found after #{steps} steps" | |
| puts " Time taken: #{(end_time - start_time) * 1000} milliseconds" | |
| -1 | |
| end | |
| def complexity_comparison | |
| puts "\nBusiness Efficiency Comparison (Big O Notation):" | |
| puts " O(1) - Constant: Employee badge lookup - BEST" | |
| puts " Like having a direct phone number" | |
| puts " O(log n) - Logarithmic: Binary search - EXCELLENT" | |
| puts " Like using a phone book efficiently" | |
| puts " O(n) - Linear: Counting inventory - GOOD" | |
| puts " Time increases proportionally with size" | |
| puts " O(n log n) - Linearithmic: Good sorting algorithms - ACCEPTABLE" | |
| puts " Like organizing files efficiently" | |
| puts " O(n²) - Quadratic: Comparing all pairs - POOR" | |
| puts " Like comparing every employee with every other" | |
| puts " O(2ⁿ) - Exponential: Trying all combinations - TERRIBLE" | |
| puts " Like trying every possible password" | |
| puts "\nReal business impact:" | |
| [10, 100, 1000, 10000].each do |n| | |
| puts " With #{n} records:" | |
| puts " O(1): 1 operation" | |
| puts " O(log n): #{Math.log2(n).ceil} operations" | |
| puts " O(n): #{n} operations" | |
| puts " O(n²): #{n * n} operations" | |
| end | |
| end | |
| end | |
| # Testing efficiency analysis | |
| analyzer = EfficiencyAnalyzer.new | |
| # O(1) example | |
| employee_db = { | |
| "EMP001" => { name: "Alice", salary: 65000 }, | |
| "EMP002" => { name: "Bob", salary: 70000 }, | |
| "EMP003" => { name: "Carol", salary: 75000 } | |
| } | |
| analyzer.constant_time_example(employee_db, "EMP002") | |
| puts "\n" + "-" * 40 | |
| # O(n) example | |
| inventory = [ | |
| { item: "Laptops", value: 50000 }, | |
| { item: "Phones", value: 30000 }, | |
| { item: "Tablets", value: 20000 }, | |
| { item: "Monitors", value: 15000 } | |
| ] | |
| analyzer.linear_time_example(inventory) | |
| puts "\n" + "-" * 40 | |
| # O(n²) example | |
| salaries = [65000, 70000, 55000, 80000, 60000] | |
| analyzer.quadratic_time_example(salaries) | |
| puts "\n" + "-" * 40 | |
| # O(log n) example | |
| customers = ["Alpha Corp", "Beta Inc", "Delta Ltd", "Echo Co", "Foxtrot Inc", "Golf Corp"] | |
| analyzer.logarithmic_time_example(customers, "Delta Ltd") | |
| puts "\n" + "-" * 40 | |
| analyzer.complexity_comparison | |
| puts "\n" + "=" * 60 | |
| puts "SUMMARY: Key Business Takeaways" | |
| puts "=" * 60 | |
| puts "\n🎯 PRACTICAL APPLICATIONS:" | |
| puts " • Arrays: Employee records, product catalogs" | |
| puts " • Linked Lists: Supply chains, process workflows" | |
| puts " • Stacks: Undo operations, function calls" | |
| puts " • Queues: Customer service, task processing" | |
| puts " • Trees: Organization charts, decision trees" | |
| puts " • Graphs: Trading networks, social connections" | |
| puts " • Hash Tables: Fast lookups (employee IDs, product codes)" | |
| puts " • Heaps: Priority queues (VIP customers, urgent tasks)" | |
| puts " • Dynamic Programming: Optimization problems, planning" | |
| puts " • Sorting: Organizing data for analysis" | |
| puts " • Searching: Finding specific records quickly" | |
| puts " • Big O: Measuring efficiency and scalability" | |
| puts "\n💡 BUSINESS WISDOM:" | |
| puts " Choose the right data structure for your business needs!" | |
| puts " Consider scalability - will it work with 1M customers?" | |
| puts " Efficiency matters - O(n²) algorithms can kill performance!" | |
| puts " Sometimes simple solutions (arrays) are perfect" | |
| puts " Complex problems often need clever solutions (dynamic programming)" | |
| puts "\n🚀 Remember: Good algorithms are like good business processes" | |
| puts " - They scale efficiently" | |
| puts " - They're reliable and predictable" | |
| puts " - They solve real problems elegantly" |
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
| # Ruby OOP Fundamentals for Business People | |
| # Think of OOP like building a company structure | |
| puts "=" * 60 | |
| puts "RUBY OOP FUNDAMENTALS - BUILDING YOUR BUSINESS" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 1. CLASSES - Your Business Blueprint | |
| # ========================================== | |
| puts "\n1. CLASSES - The Blueprint for Your Business" | |
| puts "-" * 50 | |
| # A class is like a business plan template | |
| # It defines what every business of this type should have and do | |
| # But it's not a real business until you create an instance of it | |
| class Restaurant | |
| # These are like the standard features every restaurant must have | |
| # Think of them as the "company policies" that define what makes a restaurant | |
| def initialize(name, cuisine_type) | |
| # This is like the "grand opening" method | |
| # Every time you create a new restaurant, this runs first | |
| @name = name # @ means this belongs to THIS specific restaurant | |
| @cuisine_type = cuisine_type # Each restaurant instance gets its own copy | |
| @is_open = false # All restaurants start closed | |
| @daily_revenue = 0 # Start with no money | |
| puts "🏪 Opening new restaurant: #{@name} (#{@cuisine_type} cuisine)" | |
| end | |
| # These are the actions every restaurant can perform | |
| # Think of them as "standard operating procedures" | |
| def open_for_business | |
| @is_open = true | |
| puts "🔓 #{@name} is now OPEN for business!" | |
| end | |
| def close_for_day | |
| @is_open = false | |
| puts "🔒 #{@name} is now CLOSED. Today's revenue: $#{@daily_revenue}" | |
| @daily_revenue = 0 # Reset for tomorrow | |
| end | |
| def serve_customer(order_value) | |
| if @is_open | |
| @daily_revenue += order_value | |
| puts "💰 Served customer at #{@name}. Order: $#{order_value} (Total today: $#{@daily_revenue})" | |
| else | |
| puts "❌ Sorry, #{@name} is closed!" | |
| end | |
| end | |
| # This lets other people ask about the restaurant's status | |
| # Think of it as "public information" that anyone can request | |
| def status_report | |
| status = @is_open ? "OPEN" : "CLOSED" | |
| puts "📊 #{@name} Status: #{status}, Cuisine: #{@cuisine_type}, Today's Revenue: $#{@daily_revenue}" | |
| end | |
| end | |
| # Creating actual restaurants from our blueprint | |
| # This is like actually starting real businesses using your business plan | |
| puts "\nCreating restaurants from our blueprint:" | |
| pizza_place = Restaurant.new("Mario's Pizza", "Italian") | |
| sushi_bar = Restaurant.new("Tokyo Express", "Japanese") | |
| burger_joint = Restaurant.new("Burger Heaven", "American") | |
| # Each restaurant is independent - they don't share money or status | |
| puts "\nOperating our restaurants:" | |
| pizza_place.open_for_business | |
| pizza_place.serve_customer(25.50) | |
| pizza_place.serve_customer(18.75) | |
| sushi_bar.open_for_business | |
| sushi_bar.serve_customer(45.00) | |
| # Burger joint stays closed today | |
| burger_joint.serve_customer(12.00) # This should fail | |
| puts "\nEnd of day status reports:" | |
| pizza_place.status_report | |
| sushi_bar.status_report | |
| burger_joint.status_report | |
| # ========================================== | |
| # 2. INHERITANCE - Business Expansion Models | |
| # ========================================== | |
| puts "\n\n2. INHERITANCE - Expanding Your Business Model" | |
| puts "-" * 50 | |
| # Inheritance is like creating specialized versions of your business | |
| # A FastFoodRestaurant IS A Restaurant, but with extra features | |
| class FastFoodRestaurant < Restaurant # < means "inherits from" | |
| # This gets EVERYTHING from Restaurant class, plus we can add more | |
| def initialize(name, cuisine_type, drive_thru = false) | |
| # Call the parent's initialization first (like following the basic business plan) | |
| super(name, cuisine_type) # This runs Restaurant's initialize method | |
| # Then add our special fast-food features | |
| @has_drive_thru = drive_thru | |
| @orders_per_hour = 0 | |
| puts "🚗 #{name} is a fast-food restaurant with drive-thru: #{drive_thru}" | |
| end | |
| # Override the parent's method with our faster version | |
| def serve_customer(order_value) | |
| if @is_open | |
| @daily_revenue += order_value | |
| @orders_per_hour += 1 | |
| puts "⚡ FAST service at #{@name}! Order: $#{order_value} (#{@orders_per_hour} orders this hour)" | |
| else | |
| puts "❌ Sorry, #{@name} is closed!" | |
| end | |
| end | |
| # Add completely new methods that only fast-food places have | |
| def serve_drive_thru(order_value) | |
| if @has_drive_thru && @is_open | |
| @daily_revenue += order_value | |
| @orders_per_hour += 2 # Drive-thru is even faster! | |
| puts "🚗💨 Drive-thru service at #{@name}! Order: $#{order_value}" | |
| elsif !@has_drive_thru | |
| puts "❌ #{@name} doesn't have a drive-thru!" | |
| else | |
| puts "❌ Sorry, #{@name} is closed!" | |
| end | |
| end | |
| def hourly_efficiency_report | |
| puts "📈 #{@name} served #{@orders_per_hour} customers this hour" | |
| @orders_per_hour = 0 # Reset for next hour | |
| end | |
| end | |
| puts "\nCreating specialized fast-food restaurants:" | |
| mcburgers = FastFoodRestaurant.new("McBurgers", "American", true) # With drive-thru | |
| quick_pizza = FastFoodRestaurant.new("Quick Pizza", "Italian", false) # No drive-thru | |
| puts "\nTesting inheritance and new features:" | |
| mcburgers.open_for_business # This method came from Restaurant class | |
| mcburgers.serve_customer(8.99) # This is our overridden faster version | |
| mcburgers.serve_drive_thru(12.50) # This is completely new | |
| mcburgers.hourly_efficiency_report # This is also new | |
| quick_pizza.open_for_business | |
| quick_pizza.serve_customer(15.99) | |
| quick_pizza.serve_drive_thru(10.00) # This should fail - no drive-thru! | |
| # ========================================== | |
| # 3. MODULES - Shared Business Capabilities | |
| # ========================================== | |
| puts "\n\n3. MODULES - Shared Business Capabilities" | |
| puts "-" * 50 | |
| # Modules are like business certifications or capabilities | |
| # that different types of businesses can share | |
| # Think of them as "business add-ons" that you can mix into any company | |
| module DeliveryService | |
| # This module contains everything needed to offer delivery | |
| # Any business can "include" this to gain delivery capabilities | |
| def add_delivery_option | |
| @delivery_available = true | |
| @delivery_fee = 3.99 | |
| puts "🚚 #{@name} now offers delivery service! Fee: $#{@delivery_fee}" | |
| end | |
| def deliver_order(order_value, distance) | |
| if @delivery_available && @is_open | |
| # Calculate delivery fee based on distance | |
| total_fee = @delivery_fee + (distance * 0.50) | |
| total_order = order_value + total_fee | |
| @daily_revenue += total_order | |
| puts "🏠 Delivering to customer! Order: $#{order_value}, Delivery: $#{total_fee.round(2)}" | |
| puts " Total charged: $#{total_order.round(2)}" | |
| elsif !@delivery_available | |
| puts "❌ #{@name} doesn't offer delivery!" | |
| else | |
| puts "❌ Sorry, #{@name} is closed!" | |
| end | |
| end | |
| end | |
| module LoyaltyProgram | |
| # This module handles customer loyalty points | |
| # Any business can add this to reward repeat customers | |
| def setup_loyalty_program(points_per_dollar = 1) | |
| @loyalty_program = true | |
| @points_rate = points_per_dollar | |
| @customer_points = {} # Hash to store each customer's points | |
| puts "⭐ #{@name} launched loyalty program! Earn #{@points_rate} point per $1 spent" | |
| end | |
| def serve_loyalty_customer(customer_name, order_value) | |
| if @is_open | |
| @daily_revenue += order_value | |
| if @loyalty_program | |
| # Add points for this purchase | |
| points_earned = (order_value * @points_rate).to_i | |
| @customer_points[customer_name] ||= 0 | |
| @customer_points[customer_name] += points_earned | |
| puts "💎 #{customer_name} earned #{points_earned} points! Total: #{@customer_points[customer_name]}" | |
| end | |
| else | |
| puts "❌ Sorry, #{@name} is closed!" | |
| end | |
| end | |
| def redeem_points(customer_name, points_to_use) | |
| return unless @loyalty_program && @customer_points[customer_name] | |
| if @customer_points[customer_name] >= points_to_use | |
| discount = points_to_use * 0.01 # 1 point = 1 cent | |
| @customer_points[customer_name] -= points_to_use | |
| puts "🎁 #{customer_name} redeemed #{points_to_use} points for $#{discount} discount!" | |
| return discount | |
| else | |
| puts "❌ #{customer_name} doesn't have enough points!" | |
| return 0 | |
| end | |
| end | |
| end | |
| # Now let's create restaurants that use these modules | |
| # This is called "mixing in" the modules | |
| class ModernRestaurant < Restaurant | |
| include DeliveryService # Mix in delivery capabilities | |
| include LoyaltyProgram # Mix in loyalty program capabilities | |
| # Now this class has ALL methods from: | |
| # 1. Restaurant (parent class) | |
| # 2. DeliveryService (mixed-in module) | |
| # 3. LoyaltyProgram (mixed-in module) | |
| # Plus any methods we define here | |
| def initialize(name, cuisine_type) | |
| super(name, cuisine_type) # Call parent's initialize | |
| puts "🆕 #{@name} is a modern restaurant with advanced features!" | |
| end | |
| end | |
| puts "\nCreating modern restaurants with mixed-in capabilities:" | |
| tech_cafe = ModernRestaurant.new("Tech Cafe", "Fusion") | |
| tech_cafe.open_for_business | |
| # Using inherited methods from Restaurant | |
| tech_cafe.serve_customer(22.50) | |
| # Using methods from DeliveryService module | |
| tech_cafe.add_delivery_option | |
| tech_cafe.deliver_order(18.75, 2.5) # $18.75 order, 2.5 miles away | |
| # Using methods from LoyaltyProgram module | |
| tech_cafe.setup_loyalty_program(2) # 2 points per dollar | |
| tech_cafe.serve_loyalty_customer("Alice", 25.00) | |
| tech_cafe.serve_loyalty_customer("Alice", 15.00) | |
| tech_cafe.redeem_points("Alice", 50) | |
| # ========================================== | |
| # 4. RUBY'S OBJECT MODEL - The Business Hierarchy | |
| # ========================================== | |
| puts "\n\n4. RUBY'S OBJECT MODEL - Understanding the Business Hierarchy" | |
| puts "-" * 50 | |
| # Ruby's object model is like understanding the corporate structure | |
| # Every object knows its place in the hierarchy | |
| puts "Understanding object relationships:" | |
| # Every object has a class (its direct blueprint) | |
| puts "tech_cafe's class: #{tech_cafe.class}" | |
| puts "tech_cafe is a ModernRestaurant?: #{tech_cafe.is_a?(ModernRestaurant)}" | |
| puts "tech_cafe is a Restaurant?: #{tech_cafe.is_a?(Restaurant)}" # true because of inheritance | |
| puts "tech_cafe is an Object?: #{tech_cafe.is_a?(Object)}" # true - everything inherits from Object | |
| # Classes also have classes (they're objects too!) | |
| puts "\nClasses are objects too:" | |
| puts "ModernRestaurant's class: #{ModernRestaurant.class}" | |
| puts "Restaurant's class: #{Restaurant.class}" | |
| # Method lookup chain - how Ruby finds methods | |
| puts "\nMethod lookup chain for tech_cafe:" | |
| puts tech_cafe.class.ancestors | |
| # This shows the order Ruby searches for methods: | |
| # 1. ModernRestaurant | |
| # 2. LoyaltyProgram (mixed-in module) | |
| # 3. DeliveryService (mixed-in module) | |
| # 4. Restaurant (parent class) | |
| # 5. Object (ultimate parent) | |
| # 6. Kernel (basic Ruby methods) | |
| # 7. BasicObject (absolute base) | |
| puts "\nDemonstrating method lookup:" | |
| puts "When we call tech_cafe.serve_customer(10):" | |
| puts " 1. Ruby looks in ModernRestaurant class - not found" | |
| puts " 2. Ruby looks in LoyaltyProgram module - not found" | |
| puts " 3. Ruby looks in DeliveryService module - not found" | |
| puts " 4. Ruby looks in Restaurant class - FOUND! Uses that method" | |
| # ========================================== | |
| # 5. PRACTICAL BUSINESS EXAMPLE | |
| # ========================================== | |
| puts "\n\n5. PUTTING IT ALL TOGETHER - Restaurant Chain Management" | |
| puts "-" * 50 | |
| # Let's create a comprehensive restaurant chain system | |
| # that demonstrates all OOP concepts working together | |
| module Reporting | |
| def generate_monthly_report | |
| puts "\n📋 MONTHLY REPORT for #{@name}" | |
| puts " Type: #{self.class}" | |
| puts " Status: #{@is_open ? 'Currently Open' : 'Currently Closed'}" | |
| puts " Special Features:" | |
| # Check what capabilities this restaurant has | |
| puts " - Delivery: #{respond_to?(:deliver_order) ? 'Yes' : 'No'}" | |
| puts " - Loyalty Program: #{respond_to?(:setup_loyalty_program) ? 'Yes' : 'No'}" | |
| puts " - Drive-thru: #{instance_variable_defined?(:@has_drive_thru) ? @has_drive_thru : 'No'}" | |
| puts " Today's Revenue: $#{@daily_revenue}" | |
| end | |
| end | |
| class RestaurantChain | |
| def initialize(chain_name) | |
| @chain_name = chain_name | |
| @locations = [] | |
| puts "🏢 Created restaurant chain: #{@chain_name}" | |
| end | |
| def add_location(restaurant) | |
| # Add reporting capability to any restaurant we manage | |
| restaurant.extend(Reporting) # extend adds module methods to a single object | |
| @locations << restaurant | |
| puts "➕ Added #{restaurant.instance_variable_get(:@name)} to #{@chain_name} chain" | |
| end | |
| def chain_status_report | |
| puts "\n🏢 #{@chain_name} CHAIN STATUS REPORT" | |
| puts "=" * 40 | |
| @locations.each { |location| location.generate_monthly_report } | |
| end | |
| end | |
| # Creating a restaurant chain with different types of restaurants | |
| puts "\nBuilding a restaurant chain empire:" | |
| chain = RestaurantChain.new("Delicious Foods Inc") | |
| # Add different types of restaurants to our chain | |
| location1 = Restaurant.new("Downtown Bistro", "French") | |
| location2 = FastFoodRestaurant.new("Speedy Burgers", "American", true) | |
| location3 = ModernRestaurant.new("Tech Diner", "Fusion") | |
| # Configure the modern restaurant | |
| location3.add_delivery_option | |
| location3.setup_loyalty_program | |
| # Add all locations to chain | |
| chain.add_location(location1) | |
| chain.add_location(location2) | |
| chain.add_location(location3) | |
| # Simulate some business activity | |
| location1.open_for_business | |
| location1.serve_customer(45.00) | |
| location2.open_for_business | |
| location2.serve_customer(12.99) | |
| location2.serve_drive_thru(8.50) | |
| location3.open_for_business | |
| location3.serve_customer(28.75) | |
| location3.deliver_order(22.00, 1.8) | |
| # Generate comprehensive chain report | |
| chain.chain_status_report | |
| puts "\n" + "=" * 60 | |
| puts "KEY OOP CONCEPTS SUMMARY" | |
| puts "=" * 60 | |
| puts "\n🏗️ CLASSES are blueprints (like business plans)" | |
| puts " - They define what attributes and behaviors objects will have" | |
| puts " - You create instances (actual businesses) from these blueprints" | |
| puts "\n🧬 INHERITANCE lets you create specialized versions" | |
| puts " - FastFoodRestaurant inherits from Restaurant" | |
| puts " - Gets all parent features plus can add/modify behavior" | |
| puts "\n🧩 MODULES are reusable capabilities you can mix in" | |
| puts " - DeliveryService can be added to any restaurant type" | |
| puts " - Use 'include' to mix into class, 'extend' to add to single object" | |
| puts "\n🌳 OBJECT MODEL shows the hierarchy" | |
| puts " - Every object knows its class and inheritance chain" | |
| puts " - Ruby searches up the chain to find methods" | |
| puts " - Everything ultimately inherits from Object" | |
| puts "\n💡 BUSINESS LESSON:" | |
| puts " OOP lets you model real business relationships in code" | |
| puts " - Inheritance = 'is-a' relationships (FastFood IS A Restaurant)" | |
| puts " - Modules = 'can-do' capabilities (Restaurant CAN DO delivery)" | |
| puts " - This makes code organized, reusable, and maintainable" |
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
| # Ruby Blocks, Procs & Lambdas for Business People | |
| # Think of these as different ways to package business procedures | |
| puts "=" * 60 | |
| puts "RUBY BLOCKS, PROCS & LAMBDAS - BUSINESS PROCEDURES" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 1. BLOCKS - Your Standard Operating Procedures | |
| # ========================================== | |
| puts "\n1. BLOCKS - Standard Operating Procedures (SOPs)" | |
| puts "-" * 50 | |
| # A block is like a standard procedure that you can pass to different methods | |
| # Think of it as a "how-to" instruction that can be used in various situations | |
| # Blocks are written with { } for one line or do...end for multiple lines | |
| puts "Understanding blocks through business processes:\n" | |
| # Example 1: Processing employee list with different procedures | |
| employees = ["Alice", "Bob", "Charlie", "Diana", "Eve"] | |
| puts "Our employee list: #{employees}" | |
| # Block example 1: Simple procedure passed to each method | |
| puts "\nSending welcome emails (using a block):" | |
| employees.each { |employee| puts "📧 Sending welcome email to #{employee}" } | |
| # Block example 2: Multi-line procedure with do...end | |
| puts "\nProcessing payroll (using a block with multiple steps):" | |
| employees.each do |employee| | |
| puts "💰 Processing payroll for #{employee}" | |
| puts " - Calculating hours worked" | |
| puts " - Computing tax deductions" | |
| puts " - Generating pay stub" | |
| puts " - Sending direct deposit" | |
| end | |
| # Example 2: Blocks with business logic | |
| sales_data = [1200, 800, 1500, 900, 2000, 750, 1800] | |
| puts "\nOriginal sales data: #{sales_data}" | |
| # Using select with a block to filter data (like finding high performers) | |
| high_sales = sales_data.select { |amount| amount > 1000 } | |
| puts "High sales (>$1000): #{high_sales}" | |
| # Using map with a block to transform data (like applying commission) | |
| commission_rates = sales_data.map { |amount| amount * 0.05 } # 5% commission | |
| puts "Commission earned: #{commission_rates}" | |
| # Using reduce with a block to accumulate data (like total revenue) | |
| total_revenue = sales_data.reduce(0) { |total, amount| total + amount } | |
| puts "Total revenue: $#{total_revenue}" | |
| # Example 3: Creating your own methods that accept blocks | |
| class BusinessReport | |
| def initialize(company_name) | |
| @company_name = company_name | |
| end | |
| # This method accepts a block and yields control to it | |
| def generate_report(data) | |
| puts "\n📊 #{@company_name} Business Report" | |
| puts "=" * 30 | |
| # yield passes control to the block that was given to this method | |
| # Think of it as "now execute the custom procedure the caller provided" | |
| yield(data) if block_given? # Only run block if one was provided | |
| puts "=" * 30 | |
| puts "Report completed ✅" | |
| end | |
| # Method with multiple yield points (like a procedure with multiple steps) | |
| def quarterly_review(departments) | |
| puts "\n🔍 Quarterly Review Process Started" | |
| departments.each do |dept| | |
| puts "\nReviewing #{dept} department:" | |
| yield(dept, "performance") if block_given? # First yield - performance review | |
| yield(dept, "budget") if block_given? # Second yield - budget review | |
| end | |
| puts "\n✅ Quarterly review completed" | |
| end | |
| end | |
| # Using our custom methods with blocks | |
| report_generator = BusinessReport.new("Tech Innovations Inc") | |
| # Pass a block that defines how to process the data | |
| report_generator.generate_report(sales_data) do |data| | |
| puts "Sales Summary:" | |
| puts " Total Sales: $#{data.sum}" | |
| puts " Average Sale: $#{data.sum / data.length}" | |
| puts " Best Month: $#{data.max}" | |
| puts " Worst Month: $#{data.min}" | |
| end | |
| # Using the quarterly review with a block that handles both performance and budget | |
| departments = ["Sales", "Marketing", "Engineering"] | |
| report_generator.quarterly_review(departments) do |dept, review_type| | |
| case review_type | |
| when "performance" | |
| puts " 📈 #{dept} performance: Exceeds expectations" | |
| when "budget" | |
| puts " 💰 #{dept} budget utilization: 85% used" | |
| end | |
| end | |
| # ========================================== | |
| # 2. PROCS - Reusable Business Procedures | |
| # ========================================== | |
| puts "\n\n2. PROCS - Reusable Business Procedures" | |
| puts "-" * 50 | |
| # A Proc is like a business procedure that you can save and reuse | |
| # Think of it as writing down a standard procedure once, then using it many times | |
| # Unlike blocks, Procs are objects that can be stored in variables | |
| puts "Creating reusable business procedures with Procs:\n" | |
| # Creating a Proc - like writing down a standard procedure | |
| customer_welcome_procedure = Proc.new do |customer_name, account_type| | |
| puts "🤝 Welcome #{customer_name}!" | |
| puts " Account type: #{account_type}" | |
| puts " Setting up your dashboard..." | |
| puts " Sending account confirmation email..." | |
| puts " Assignment to customer success manager: pending" | |
| end | |
| # Using the Proc - like following the written procedure | |
| puts "Welcoming new customers using our standard procedure:" | |
| customer_welcome_procedure.call("Alice Johnson", "Premium") | |
| customer_welcome_procedure.call("Bob Smith", "Standard") | |
| # You can also use .() as shorthand for .call() | |
| customer_welcome_procedure.("Charlie Brown", "Enterprise") | |
| # Example: Creating different business calculation procedures | |
| puts "\nBusiness calculation procedures:" | |
| # Tax calculation procedure | |
| tax_calculator = Proc.new { |amount| amount * 0.08 } # 8% tax | |
| # Discount calculation procedure | |
| discount_calculator = Proc.new do |amount, customer_tier| | |
| case customer_tier | |
| when "bronze" then amount * 0.05 # 5% discount | |
| when "silver" then amount * 0.10 # 10% discount | |
| when "gold" then amount * 0.15 # 15% discount | |
| else 0 # No discount | |
| end | |
| end | |
| # Commission calculation procedure | |
| commission_calculator = Proc.new { |sale_amount| sale_amount * 0.07 } # 7% commission | |
| # Using these procedures in business operations | |
| order_amount = 1000 | |
| customer_tier = "silver" | |
| tax = tax_calculator.call(order_amount) | |
| discount = discount_calculator.call(order_amount, customer_tier) | |
| commission = commission_calculator.call(order_amount) | |
| puts "Order processing:" | |
| puts " Order amount: $#{order_amount}" | |
| puts " Customer tier: #{customer_tier}" | |
| puts " Tax: $#{tax}" | |
| puts " Discount: $#{discount}" | |
| puts " Sales commission: $#{commission}" | |
| puts " Final total: $#{order_amount + tax - discount}" | |
| # Example: Passing Procs to methods (like assigning procedures to different processes) | |
| class OrderProcessor | |
| def process_orders(orders, tax_proc, discount_proc) | |
| puts "\n🏭 Processing orders with custom procedures:" | |
| orders.each do |order| | |
| customer = order[:customer] | |
| amount = order[:amount] | |
| tier = order[:tier] | |
| tax = tax_proc.call(amount) | |
| discount = discount_proc.call(amount, tier) | |
| final_total = amount + tax - discount | |
| puts " #{customer}: $#{amount} → Final: $#{final_total.round(2)} (tax: $#{tax}, discount: $#{discount})" | |
| end | |
| end | |
| end | |
| # Sample orders | |
| orders = [ | |
| { customer: "Alice Corp", amount: 5000, tier: "gold" }, | |
| { customer: "Bob Industries", amount: 2000, tier: "silver" }, | |
| { customer: "Charlie LLC", amount: 1000, tier: "bronze" } | |
| ] | |
| processor = OrderProcessor.new | |
| processor.process_orders(orders, tax_calculator, discount_calculator) | |
| # ========================================== | |
| # 3. LAMBDAS - Strict Business Procedures | |
| # ========================================== | |
| puts "\n\n3. LAMBDAS - Strict Business Procedures" | |
| puts "-" * 50 | |
| # A lambda is like a Proc, but with stricter rules | |
| # Think of it as a formal business procedure with exact requirements | |
| # Lambdas check the number of arguments and handle returns differently | |
| puts "Creating strict business procedures with lambdas:\n" | |
| # Creating a lambda - notice the -> syntax (stabby lambda) | |
| strict_discount_calculator = lambda do |amount, tier, years_customer| | |
| base_discount = case tier | |
| when "bronze" then 0.05 | |
| when "silver" then 0.10 | |
| when "gold" then 0.15 | |
| else 0.0 | |
| end | |
| # Loyalty bonus based on years as customer | |
| loyalty_bonus = years_customer * 0.01 # 1% per year | |
| total_discount_rate = base_discount + loyalty_bonus | |
| # Cap the discount at 25% | |
| total_discount_rate = [total_discount_rate, 0.25].min | |
| discount = amount * total_discount_rate | |
| puts " Discount calculation: #{tier} (#{base_discount*100}%) + loyalty (#{loyalty_bonus*100}%) = #{total_discount_rate*100}%" | |
| discount | |
| end | |
| # Alternative syntax for simple lambdas | |
| simple_tax_calc = ->(amount) { amount * 0.08 } | |
| # Demonstrating lambda strictness | |
| puts "Lambda strictness demonstration:" | |
| begin | |
| # This works - correct number of arguments | |
| discount = strict_discount_calculator.call(1000, "silver", 3) | |
| puts "✅ Correct args: Discount = $#{discount.round(2)}" | |
| rescue ArgumentError => e | |
| puts "❌ Error: #{e.message}" | |
| end | |
| begin | |
| # This fails - wrong number of arguments (lambdas are strict!) | |
| discount = strict_discount_calculator.call(1000, "silver") # Missing years_customer | |
| puts "Discount = $#{discount}" | |
| rescue ArgumentError => e | |
| puts "❌ Lambda error: #{e.message}" | |
| end | |
| # Compare with Proc - Procs are more forgiving | |
| lenient_proc = Proc.new { |amount, tier, years| puts "Proc got: #{amount}, #{tier}, #{years}" } | |
| puts "\nComparing Proc vs Lambda argument handling:" | |
| puts "Proc with missing arguments:" | |
| lenient_proc.call(1000, "gold") # Works - missing args become nil | |
| puts "Lambda with missing arguments:" | |
| begin | |
| strict_discount_calculator.call(1000, "gold") # Fails - strict about arguments | |
| rescue ArgumentError => e | |
| puts "❌ #{e.message}" | |
| end | |
| # ========================================== | |
| # 4. PRACTICAL BUSINESS APPLICATIONS | |
| # ========================================== | |
| puts "\n\n4. PRACTICAL BUSINESS APPLICATIONS" | |
| puts "-" * 50 | |
| # Real-world business scenario: E-commerce order processing system | |
| class EcommerceSystem | |
| def initialize | |
| @payment_processors = {} | |
| @shipping_calculators = {} | |
| @notification_handlers = {} | |
| end | |
| # Register different business procedures for different operations | |
| def register_payment_processor(name, processor_proc) | |
| @payment_processors[name] = processor_proc | |
| puts "💳 Registered payment processor: #{name}" | |
| end | |
| def register_shipping_calculator(name, calculator_lambda) | |
| @shipping_calculators[name] = calculator_lambda | |
| puts "🚚 Registered shipping calculator: #{name}" | |
| end | |
| def register_notification_handler(notification_type, &handler_block) | |
| # &handler_block converts a block to a Proc | |
| @notification_handlers[notification_type] = handler_block | |
| puts "📧 Registered notification handler: #{notification_type}" | |
| end | |
| def process_order(order_details) | |
| puts "\n🛒 Processing order ##{order_details[:id]}" | |
| # Use the appropriate payment processor | |
| payment_method = order_details[:payment_method] | |
| if processor = @payment_processors[payment_method] | |
| processor.call(order_details[:amount], order_details[:customer]) | |
| end | |
| # Calculate shipping using the appropriate method | |
| shipping_method = order_details[:shipping_method] | |
| if calculator = @shipping_calculators[shipping_method] | |
| shipping_cost = calculator.call(order_details[:weight], order_details[:distance]) | |
| puts "📦 Shipping cost: $#{shipping_cost}" | |
| end | |
| # Send appropriate notifications | |
| if handler = @notification_handlers[:order_confirmation] | |
| handler.call(order_details[:customer], order_details[:id]) | |
| end | |
| puts "✅ Order ##{order_details[:id]} processed successfully" | |
| end | |
| end | |
| # Setting up the e-commerce system with different procedures | |
| ecommerce = EcommerceSystem.new | |
| # Register payment processors (using Procs) | |
| credit_card_processor = Proc.new do |amount, customer| | |
| puts "💳 Processing credit card payment of $#{amount} for #{customer}" | |
| puts " - Validating card details" | |
| puts " - Charging card" | |
| puts " - Sending receipt" | |
| end | |
| paypal_processor = Proc.new do |amount, customer| | |
| puts "🏦 Processing PayPal payment of $#{amount} for #{customer}" | |
| puts " - Redirecting to PayPal" | |
| puts " - Confirming payment" | |
| puts " - Returning to store" | |
| end | |
| ecommerce.register_payment_processor("credit_card", credit_card_processor) | |
| ecommerce.register_payment_processor("paypal", paypal_processor) | |
| # Register shipping calculators (using lambdas for strict argument checking) | |
| standard_shipping = lambda do |weight, distance| | |
| base_cost = 5.99 | |
| weight_cost = weight * 0.50 # $0.50 per pound | |
| distance_cost = distance * 0.10 # $0.10 per mile | |
| base_cost + weight_cost + distance_cost | |
| end | |
| express_shipping = lambda do |weight, distance| | |
| base_cost = 15.99 | |
| weight_cost = weight * 0.75 # Higher rate for express | |
| distance_cost = distance * 0.15 | |
| base_cost + weight_cost + distance_cost | |
| end | |
| ecommerce.register_shipping_calculator("standard", standard_shipping) | |
| ecommerce.register_shipping_calculator("express", express_shipping) | |
| # Register notification handlers (using blocks) | |
| ecommerce.register_notification_handler(:order_confirmation) do |customer, order_id| | |
| puts "📧 Sending order confirmation to #{customer}" | |
| puts " Order ##{order_id} has been received and is being processed" | |
| puts " You will receive shipping updates soon" | |
| end | |
| # Process some sample orders | |
| sample_orders = [ | |
| { | |
| id: "ORD001", | |
| customer: "Alice Johnson", | |
| amount: 99.99, | |
| payment_method: "credit_card", | |
| shipping_method: "standard", | |
| weight: 2.5, | |
| distance: 25 | |
| }, | |
| { | |
| id: "ORD002", | |
| customer: "Bob Smith", | |
| amount: 149.99, | |
| payment_method: "paypal", | |
| shipping_method: "express", | |
| weight: 1.2, | |
| distance: 15 | |
| } | |
| ] | |
| sample_orders.each { |order| ecommerce.process_order(order) } | |
| # ========================================== | |
| # 5. WHEN TO USE WHICH: BUSINESS DECISION GUIDE | |
| # ========================================== | |
| puts "\n\n5. WHEN TO USE WHICH: BUSINESS DECISION GUIDE" | |
| puts "-" * 50 | |
| puts "\n📋 BLOCKS - Use for immediate, one-time procedures:" | |
| puts " ✅ Processing a list of items with custom logic" | |
| puts " ✅ Configuring behavior in a method call" | |
| puts " ✅ Event handling (like 'when this happens, do that')" | |
| puts " ✅ Quick transformations and filters" | |
| # Example: Quick data processing | |
| monthly_revenues = [45000, 52000, 48000, 61000, 55000, 59000] | |
| puts "\nBlock example - Quick revenue analysis:" | |
| quarterly_avg = monthly_revenues.each_slice(3).map do |quarter| | |
| quarter.sum / quarter.length | |
| end | |
| puts "Quarterly averages: #{quarterly_avg}" | |
| puts "\n📦 PROCS - Use for reusable business procedures:" | |
| puts " ✅ Standard calculations used in multiple places" | |
| puts " ✅ Business rules that might change" | |
| puts " ✅ Configurable behavior (like plugins)" | |
| puts " ✅ When you need to store the procedure for later" | |
| # Example: Configurable business rules | |
| regional_tax_rates = { | |
| "CA" => Proc.new { |amount| amount * 0.0875 }, # California: 8.75% | |
| "NY" => Proc.new { |amount| amount * 0.08 }, # New York: 8% | |
| "TX" => Proc.new { |amount| amount * 0.0625 }, # Texas: 6.25% | |
| "FL" => Proc.new { |amount| 0 } # Florida: 0% (no state tax) | |
| } | |
| puts "\nProc example - Regional tax calculation:" | |
| order_amount = 1000 | |
| ["CA", "NY", "TX", "FL"].each do |state| | |
| tax = regional_tax_rates[state].call(order_amount) | |
| puts " #{state}: $#{order_amount} order → $#{tax} tax" | |
| end | |
| puts "\n🎯 LAMBDAS - Use for strict, formal procedures:" | |
| puts " ✅ Critical calculations that must have exact inputs" | |
| puts " ✅ APIs and interfaces with strict contracts" | |
| puts " ✅ Mathematical formulas and financial calculations" | |
| puts " ✅ When argument count validation is important" | |
| # Example: Formal financial calculations | |
| compound_interest_calculator = lambda do |principal, rate, time, compounds_per_year| | |
| # Formula: A = P(1 + r/n)^(nt) | |
| # This MUST have exactly 4 arguments - no exceptions! | |
| rate_per_period = rate / compounds_per_year | |
| total_periods = compounds_per_year * time | |
| final_amount = principal * ((1 + rate_per_period) ** total_periods) | |
| { | |
| principal: principal, | |
| final_amount: final_amount.round(2), | |
| interest_earned: (final_amount - principal).round(2) | |
| } | |
| end | |
| puts "\nLambda example - Compound interest calculation:" | |
| investment_result = compound_interest_calculator.call(10000, 0.05, 10, 12) | |
| puts " Investment: $#{investment_result[:principal]}" | |
| puts " After 10 years: $#{investment_result[:final_amount]}" | |
| puts " Interest earned: $#{investment_result[:interest_earned]}" | |
| # ========================================== | |
| # 6. ADVANCED BUSINESS PATTERNS | |
| # ========================================== | |
| puts "\n\n6. ADVANCED BUSINESS PATTERNS" | |
| puts "-" * 50 | |
| # Pattern 1: Strategy Pattern - Different business strategies | |
| class MarketingCampaign | |
| def initialize(name) | |
| @name = name | |
| @strategies = {} | |
| end | |
| def add_strategy(channel, strategy_proc) | |
| @strategies[channel] = strategy_proc | |
| puts "📢 Added #{channel} strategy to #{@name} campaign" | |
| end | |
| def execute_campaign(budget_per_channel) | |
| puts "\n🚀 Executing #{@name} campaign:" | |
| @strategies.each do |channel, strategy| | |
| budget = budget_per_channel[channel] || 0 | |
| if budget > 0 | |
| puts "\n#{channel.upcase} CHANNEL:" | |
| strategy.call(budget) | |
| end | |
| end | |
| end | |
| end | |
| # Create different marketing strategies | |
| email_strategy = Proc.new do |budget| | |
| emails_to_send = (budget / 0.05).to_i # $0.05 per email | |
| puts " 📧 Sending #{emails_to_send} personalized emails" | |
| puts " 📊 Expected open rate: 25%" | |
| puts " 📈 Expected conversion rate: 3%" | |
| end | |
| social_media_strategy = Proc.new do |budget| | |
| posts_to_boost = (budget / 25).to_i # $25 per boosted post | |
| puts " 📱 Boosting #{posts_to_boost} social media posts" | |
| puts " 👥 Expected reach: #{posts_to_boost * 5000} people" | |
| puts " 💬 Expected engagement rate: 8%" | |
| end | |
| google_ads_strategy = Proc.new do |budget| | |
| clicks_expected = (budget / 2.50).to_i # $2.50 per click | |
| puts " 🔍 Google Ads campaign" | |
| puts " 👆 Expected clicks: #{clicks_expected}" | |
| puts " 📊 Expected conversion rate: 5%" | |
| end | |
| # Execute a marketing campaign | |
| campaign = MarketingCampaign.new("Spring Product Launch") | |
| campaign.add_strategy(:email, email_strategy) | |
| campaign.add_strategy(:social_media, social_media_strategy) | |
| campaign.add_strategy(:google_ads, google_ads_strategy) | |
| budget_allocation = { | |
| email: 500, | |
| social_media: 750, | |
| google_ads: 1000 | |
| } | |
| campaign.execute_campaign(budget_allocation) | |
| # Pattern 2: Observer Pattern - Business event notifications | |
| class BusinessEventSystem | |
| def initialize | |
| @observers = Hash.new { |h, k| h[k] = [] } | |
| end | |
| def subscribe(event_type, &observer_block) | |
| @observers[event_type] << observer_block | |
| puts "👂 Subscribed to #{event_type} events" | |
| end | |
| def notify(event_type, event_data) | |
| puts "\n📡 Broadcasting #{event_type} event:" | |
| @observers[event_type].each do |observer| | |
| observer.call(event_data) | |
| end | |
| end | |
| end | |
| # Set up business event system | |
| events = BusinessEventSystem.new | |
| # Subscribe different departments to relevant events | |
| events.subscribe(:new_customer) do |customer_data| | |
| puts " 🎯 Marketing: Adding #{customer_data[:name]} to email list" | |
| puts " 🎯 Marketing: Assigning to nurture sequence" | |
| end | |
| events.subscribe(:new_customer) do |customer_data| | |
| puts " 🤝 Sales: Creating lead record for #{customer_data[:name]}" | |
| puts " 🤝 Sales: Scheduling follow-up call" | |
| end | |
| events.subscribe(:large_order) do |order_data| | |
| puts " 🏆 Management: Large order alert! $#{order_data[:amount]} from #{order_data[:customer]}" | |
| puts " 🏆 Management: Flagging for personal follow-up" | |
| end | |
| events.subscribe(:large_order) do |order_data| | |
| puts " 📦 Fulfillment: Priority processing for order ##{order_data[:id]}" | |
| puts " 📦 Fulfillment: Ensuring next-day shipping" | |
| end | |
| # Trigger some business events | |
| events.notify(:new_customer, { name: "Acme Corp", email: "[email protected]", industry: "Manufacturing" }) | |
| events.notify(:large_order, { id: "ORD-5678", customer: "BigClient Inc", amount: 50000 }) | |
| # ========================================== | |
| # 7. PERFORMANCE AND MEMORY CONSIDERATIONS | |
| # ========================================== | |
| puts "\n\n7. PERFORMANCE AND MEMORY CONSIDERATIONS" | |
| puts "-" * 50 | |
| puts "\n💡 BUSINESS PERFORMANCE TIPS:" | |
| puts "\n🚀 Speed Considerations:" | |
| puts " • Blocks: Fastest (no object creation)" | |
| puts " • Procs: Moderate (object creation overhead)" | |
| puts " • Lambdas: Moderate (object creation + argument checking)" | |
| puts "\n💾 Memory Considerations:" | |
| puts " • Blocks: Least memory (temporary)" | |
| puts " • Procs: More memory (stored as objects)" | |
| puts " • Lambdas: Similar to Procs" | |
| puts "\n🎯 Best Practices for Business Applications:" | |
| puts " • Use blocks for one-time operations (like processing reports)" | |
| puts " • Use Procs for reusable business logic (like tax calculations)" | |
| puts " • Use lambdas for critical operations (like financial calculations)" | |
| puts " • Cache expensive Procs/lambdas instead of recreating them" | |
| # Example: Caching expensive business calculations | |
| class BusinessCalculator | |
| def initialize | |
| @calculation_cache = {} | |
| end | |
| def get_calculator(calculation_type) | |
| # Cache the Proc so we don't create it every time | |
| @calculation_cache[calculation_type] ||= case calculation_type | |
| when :roi | |
| lambda { |profit, investment| ((profit - investment) / investment.to_f * 100).round(2) } | |
| when :break_even | |
| lambda { |fixed_costs, price_per_unit, variable_cost_per_unit| | |
| (fixed_costs / (price_per_unit - variable_cost_per_unit)).ceil | |
| } | |
| when :markup | |
| lambda { |cost, markup_percentage| cost * (1 + markup_percentage / 100.0) } | |
| end | |
| end | |
| end | |
| calculator = BusinessCalculator.new | |
| # These will reuse cached lambdas | |
| roi_calc = calculator.get_calculator(:roi) | |
| break_even_calc = calculator.get_calculator(:break_even) | |
| puts "\nCached calculation examples:" | |
| puts "ROI: #{roi_calc.call(15000, 10000)}%" | |
| puts "Break-even point: #{break_even_calc.call(50000, 25, 10)} units" | |
| puts "\n" + "=" * 60 | |
| puts "KEY CONCEPTS SUMMARY" | |
| puts "=" * 60 | |
| puts "\n🧱 BLOCKS are like verbal instructions:" | |
| puts " • Given on the spot for immediate use" | |
| puts " • Can't be saved for later" | |
| puts " • Perfect for 'do this with each item' scenarios" | |
| puts "\n📋 PROCS are like written procedures:" | |
| puts " • Can be saved and reused multiple times" | |
| puts " • Flexible with arguments (forgiving)" | |
| puts " • Great for configurable business logic" | |
| puts "\n📄 LAMBDAS are like formal contracts:" | |
| puts " • Strict about requirements (argument count)" | |
| puts " • Professional and reliable" | |
| puts " • Best for critical business calculations" | |
| puts "\n🎯 BUSINESS TAKEAWAY:" | |
| puts " These tools let you package business logic into reusable pieces" | |
| puts " Choose based on formality: Blocks (casual) → Procs (flexible) → Lambdas (strict)" | |
| puts " This makes your code more organized and business logic more maintainable" |
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
| # Ruby Variable Scoping for Business People | |
| # Think of variable scope like information access levels in your company | |
| puts "=" * 60 | |
| puts "RUBY VARIABLE SCOPING - COMPANY INFORMATION ACCESS" | |
| puts "=" * 60 | |
| # ========================================== | |
| # 1. LOCAL VARIABLES - Department-Level Information | |
| # ========================================== | |
| puts "\n1. LOCAL VARIABLES - Department-Level Information" | |
| puts "-" * 50 | |
| # Local variables are like information that exists only within a specific department | |
| # They start with lowercase letters or underscores | |
| # They can't be accessed from outside their "department" (scope) | |
| def sales_department_meeting | |
| # These variables only exist inside this meeting (method) | |
| monthly_target = 100000 # Local variable - only sales team knows this | |
| current_sales = 85000 # Local variable - department-specific data | |
| team_size = 5 # Local variable - internal info | |
| puts "🏢 SALES DEPARTMENT MEETING:" | |
| puts " Monthly target: $#{monthly_target}" | |
| puts " Current sales: $#{current_sales}" | |
| puts " Team size: #{team_size} people" | |
| # Calculate department-specific metrics | |
| if current_sales >= monthly_target | |
| performance_status = "exceeding target" | |
| else | |
| performance_status = "below target" | |
| end | |
| puts " Status: #{performance_status}" | |
| # Local variables die when the method ends (meeting is over) | |
| return "Sales meeting completed" | |
| end | |
| def marketing_department_meeting | |
| # These are completely separate local variables | |
| # Even though they have the same names, they're different "conversations" | |
| monthly_target = 50000 # Different target than sales | |
| current_performance = 42000 # Different metric | |
| team_size = 3 # Different team size | |
| puts "\n🎯 MARKETING DEPARTMENT MEETING:" | |
| puts " Monthly budget: $#{monthly_target}" | |
| puts " Current spend: $#{current_performance}" | |
| puts " Team size: #{team_size} people" | |
| return "Marketing meeting completed" | |
| end | |
| # Run the department meetings | |
| sales_result = sales_department_meeting | |
| marketing_result = marketing_department_meeting | |
| puts "\nMeeting results:" | |
| puts " #{sales_result}" | |
| puts " #{marketing_result}" | |
| # Try to access local variables from outside their scope (this would cause an error) | |
| puts "\nTrying to access department-internal information from outside:" | |
| begin | |
| puts "Sales target: #{monthly_target}" # This will fail - variable doesn't exist here | |
| rescue NameError => e | |
| puts "❌ Error: #{e.message}" | |
| puts " (You can't access department-internal info from outside the department)" | |
| end | |
| # Example: Local variables in different scopes | |
| def project_alpha | |
| project_name = "Alpha" | |
| budget = 250000 | |
| puts "\n📊 PROJECT ALPHA SCOPE:" | |
| puts " Project: #{project_name}" | |
| puts " Budget: $#{budget}" | |
| # Creating a sub-scope (like a sub-committee) | |
| 3.times do |week| | |
| weekly_progress = (week + 1) * 25 # This only exists in this loop | |
| puts " Week #{week + 1}: #{weekly_progress}% complete" | |
| end | |
| # weekly_progress doesn't exist here - it was only in the loop scope | |
| puts " Project summary complete" | |
| end | |
| project_alpha | |
| # ========================================== | |
| # 2. INSTANCE VARIABLES - Employee Personal Information | |
| # ========================================== | |
| puts "\n\n2. INSTANCE VARIABLES - Employee Personal Information" | |
| puts "-" * 50 | |
| # Instance variables are like personal information that belongs to a specific employee | |
| # They start with @ and are accessible throughout that employee's (object's) methods | |
| # Each employee (object) has their own copy of these variables | |
| class Employee | |
| # When an employee is hired (object is created) | |
| def initialize(name, department, salary) | |
| @name = name # @ means "this belongs to THIS specific employee" | |
| @department = department | |
| @salary = salary | |
| @performance_score = 0 | |
| @projects_completed = 0 | |
| puts "🆕 New employee hired: #{@name} in #{@department}" | |
| end | |
| # Employee methods can access their own information anywhere | |
| def introduce | |
| puts "👋 Hi, I'm #{@name} from #{@department}. I earn $#{@salary}." | |
| end | |
| def complete_project(project_name) | |
| @projects_completed += 1 # Employee updates their own record | |
| @performance_score += 10 | |
| puts "✅ #{@name} completed #{project_name}" | |
| puts " Projects completed: #{@projects_completed}" | |
| puts " Performance score: #{@performance_score}" | |
| end | |
| def get_promotion(new_salary, new_department = nil) | |
| old_salary = @salary | |
| @salary = new_salary | |
| @department = new_department if new_department | |
| puts "🎉 #{@name} got promoted!" | |
| puts " Salary: $#{old_salary} → $#{@salary}" | |
| puts " Department: #{@department}" if new_department | |
| end | |
| def annual_review | |
| puts "\n📋 ANNUAL REVIEW for #{@name}:" | |
| puts " Department: #{@department}" | |
| puts " Current salary: $#{@salary}" | |
| puts " Projects completed: #{@projects_completed}" | |
| puts " Performance score: #{@performance_score}" | |
| # Performance-based raise calculation using instance variables | |
| if @performance_score >= 50 | |
| bonus = @salary * 0.10 | |
| puts " 🏆 Excellent performance! Bonus: $#{bonus}" | |
| elsif @performance_score >= 30 | |
| bonus = @salary * 0.05 | |
| puts " 👍 Good performance! Bonus: $#{bonus}" | |
| else | |
| puts " 📈 Needs improvement" | |
| end | |
| end | |
| end | |
| # Creating employees (each gets their own instance variables) | |
| puts "\nHiring employees:" | |
| alice = Employee.new("Alice Johnson", "Engineering", 75000) | |
| bob = Employee.new("Bob Smith", "Sales", 65000) | |
| carol = Employee.new("Carol Davis", "Marketing", 60000) | |
| # Each employee has their own separate instance variables | |
| puts "\nEmployee introductions:" | |
| alice.introduce | |
| bob.introduce | |
| carol.introduce | |
| # Employees working independently (each updates their own variables) | |
| puts "\nWork activities:" | |
| alice.complete_project("Website Redesign") | |
| alice.complete_project("Database Optimization") | |
| bob.complete_project("Q1 Sales Campaign") | |
| bob.complete_project("Client Onboarding System") | |
| bob.complete_project("Sales Training Program") | |
| carol.complete_project("Brand Guidelines") | |
| # Promotions (changing instance variables) | |
| puts "\nPromotions:" | |
| alice.get_promotion(85000) | |
| bob.get_promotion(70000, "Sales Management") | |
| # Annual reviews (accessing all instance variables) | |
| alice.annual_review | |
| bob.annual_review | |
| carol.annual_review | |
| # ========================================== | |
| # 3. CLASS VARIABLES - Company-Wide Policies | |
| # ========================================== | |
| puts "\n\n3. CLASS VARIABLES - Company-Wide Policies" | |
| puts "-" * 50 | |
| # Class variables are like company-wide policies that apply to ALL employees | |
| # They start with @@ and are shared by all instances of the class | |
| # Think of them as "company handbook" information | |
| class Company | |
| # Class variables - shared by ALL employees in the company | |
| @@company_name = "Tech Innovations Inc" | |
| @@total_employees = 0 | |
| @@company_revenue = 0 | |
| @@health_insurance_provider = "HealthCorp" | |
| @@vacation_days_per_year = 20 | |
| def initialize(employee_name, department, salary) | |
| @employee_name = employee_name # Instance variable - belongs to this employee | |
| @department = department | |
| @salary = salary | |
| # Update company-wide statistics (class variables) | |
| @@total_employees += 1 | |
| @@company_revenue += salary # Assume salary contributes to revenue planning | |
| puts "🏢 #{@employee_name} joined #{@@company_name}" | |
| puts " Total employees now: #{@@total_employees}" | |
| end | |
| # Method to access company-wide information | |
| def company_info | |
| puts "\n🏢 COMPANY INFORMATION (same for all employees):" | |
| puts " Company: #{@@company_name}" | |
| puts " Total employees: #{@@total_employees}" | |
| puts " Projected revenue: $#{@@company_revenue}" | |
| puts " Health insurance: #{@@health_insurance_provider}" | |
| puts " Vacation days: #{@@vacation_days_per_year} per year" | |
| end | |
| def personal_info | |
| puts "\n👤 PERSONAL INFORMATION (specific to #{@employee_name}):" | |
| puts " Name: #{@employee_name}" | |
| puts " Department: #{@department}" | |
| puts " Salary: $#{@salary}" | |
| end | |
| # Class method to change company-wide policies | |
| def self.update_company_policy(policy, new_value) | |
| case policy | |
| when :vacation_days | |
| @@vacation_days_per_year = new_value | |
| puts "📋 Company policy updated: Vacation days changed to #{new_value}" | |
| when :health_insurance | |
| @@health_insurance_provider = new_value | |
| puts "📋 Company policy updated: Health insurance changed to #{new_value}" | |
| when :company_name | |
| @@company_name = new_value | |
| puts "📋 Company rebranded to: #{new_value}" | |
| end | |
| end | |
| # Class method to get company statistics | |
| def self.company_statistics | |
| puts "\n📊 COMPANY STATISTICS:" | |
| puts " Company: #{@@company_name}" | |
| puts " Total employees: #{@@total_employees}" | |
| puts " Total salary budget: $#{@@company_revenue}" | |
| puts " Average salary: $#{@@company_revenue / @@total_employees}" if @@total_employees > 0 | |
| end | |
| end | |
| # Hiring employees (each one updates the class variables) | |
| puts "\nBuilding our company:" | |
| emp1 = Company.new("David Wilson", "Engineering", 80000) | |
| emp2 = Company.new("Emma Brown", "Sales", 70000) | |
| emp3 = Company.new("Frank Miller", "Marketing", 65000) | |
| # All employees see the same company information (class variables) | |
| puts "\nCompany information as seen by different employees:" | |
| emp1.company_info # Same information for everyone | |
| emp2.company_info # Same information for everyone | |
| # But personal information is different (instance variables) | |
| puts "\nPersonal information varies by employee:" | |
| emp1.personal_info # Different for each employee | |
| emp2.personal_info # Different for each employee | |
| emp3.personal_info # Different for each employee | |
| # Changing company-wide policies affects everyone | |
| puts "\nUpdating company policies:" | |
| Company.update_company_policy(:vacation_days, 25) | |
| Company.update_company_policy(:health_insurance, "BetterHealth Inc") | |
| # All employees now see the updated policies | |
| puts "\nUpdated company info (same for all employees):" | |
| emp1.company_info | |
| # Company-wide statistics | |
| Company.company_statistics | |
| # ========================================== | |
| # 4. GLOBAL VARIABLES - Industry Standards | |
| # ========================================== | |
| puts "\n\n4. GLOBAL VARIABLES - Industry-Wide Standards" | |
| puts "-" * 50 | |
| # Global variables are like industry-wide standards that everyone follows | |
| # They start with $ and can be accessed from anywhere in the program | |
| # Think of them as "universal business standards" | |
| # Define global variables (industry standards) | |
| $minimum_wage = 15.00 # Industry minimum wage | |
| $standard_work_week = 40 # Standard work week hours | |
| $overtime_multiplier = 1.5 # Overtime pay multiplier | |
| $industry_tax_rate = 0.15 # Standard industry tax rate | |
| puts "💼 INDUSTRY STANDARDS (Global Variables):" | |
| puts " Minimum wage: $#{$minimum_wage}/hour" | |
| puts " Standard work week: #{$standard_work_week} hours" | |
| puts " Overtime multiplier: #{$overtime_multiplier}x" | |
| puts " Industry tax rate: #{($industry_tax_rate * 100).to_i}%" | |
| class PayrollSystem | |
| def initialize(company_name) | |
| @company_name = company_name # Instance variable | |
| puts "\n💰 Payroll system initialized for #{@company_name}" | |
| end | |
| def calculate_weekly_pay(employee_name, hourly_rate, hours_worked) | |
| puts "\n📊 Calculating pay for #{employee_name}:" | |
| puts " Hourly rate: $#{hourly_rate}" | |
| puts " Hours worked: #{hours_worked}" | |
| # Use global variables for industry standards | |
| if hourly_rate < $minimum_wage | |
| puts " ⚠️ Adjusting to minimum wage: $#{$minimum_wage}" | |
| hourly_rate = $minimum_wage | |
| end | |
| # Calculate regular and overtime pay using global standards | |
| if hours_worked <= $standard_work_week | |
| regular_pay = hours_worked * hourly_rate | |
| overtime_pay = 0 | |
| total_hours_overtime = 0 | |
| else | |
| regular_pay = $standard_work_week * hourly_rate | |
| overtime_hours = hours_worked - $standard_work_week | |
| overtime_pay = overtime_hours * hourly_rate * $overtime_multiplier | |
| total_hours_overtime = overtime_hours | |
| end | |
| gross_pay = regular_pay + overtime_pay | |
| taxes = gross_pay * $industry_tax_rate | |
| net_pay = gross_pay - taxes | |
| puts " Regular pay (#{[$standard_work_week, hours_worked].min} hours): $#{regular_pay.round(2)}" | |
| if total_hours_overtime > 0 | |
| puts " Overtime pay (#{total_hours_overtime} hours at #{$overtime_multiplier}x): $#{overtime_pay.round(2)}" | |
| end | |
| puts " Gross pay: $#{gross_pay.round(2)}" | |
| puts " Taxes (#{($industry_tax_rate * 100).to_i}%): $#{taxes.round(2)}" | |
| puts " Net pay: $#{net_pay.round(2)}" | |
| net_pay.round(2) | |
| end | |
| end | |
| # Different companies using the same global standards | |
| tech_payroll = PayrollSystem.new("Tech Innovations") | |
| retail_payroll = PayrollSystem.new("Retail Solutions") | |
| # Calculate pay using global industry standards | |
| tech_payroll.calculate_weekly_pay("Alice", 25.00, 42) # 2 hours overtime | |
| retail_payroll.calculate_weekly_pay("Bob", 12.00, 35) # Below minimum wage, under 40 hours | |
| tech_payroll.calculate_weekly_pay("Charlie", 30.00, 50) # 10 hours overtime | |
| # Industry standards change (affecting everyone globally) | |
| puts "\n📢 INDUSTRY UPDATE: New standards announced!" | |
| $minimum_wage = 16.50 | |
| $overtime_multiplier = 1.75 | |
| puts " New minimum wage: $#{$minimum_wage}/hour" | |
| puts " New overtime multiplier: #{$overtime_multiplier}x" | |
| # Recalculate with new global standards | |
| puts "\nRecalculating with new industry standards:" | |
| retail_payroll.calculate_weekly_pay("Bob", 12.00, 35) # Now gets higher minimum wage | |
| # ========================================== | |
| # 5. SCOPE HIERARCHY AND VARIABLE LOOKUP | |
| # ========================================== | |
| puts "\n\n5. SCOPE HIERARCHY - How Ruby Finds Variables" | |
| puts "-" * 50 | |
| # Ruby looks for variables in a specific order (like a company hierarchy) | |
| # This is called the "scope chain" or "variable lookup" | |
| $company_motto = "Innovation Through Excellence" # Global variable | |
| class Department | |
| @@department_budget = 500000 # Class variable (shared by all departments) | |
| def initialize(dept_name, manager_name) | |
| @dept_name = dept_name # Instance variable (specific to this department) | |
| @manager = manager_name | |
| end | |
| def demonstrate_variable_lookup | |
| local_meeting_agenda = "Q3 Planning" # Local variable (only in this method) | |
| puts "\n🔍 VARIABLE LOOKUP DEMONSTRATION:" | |
| puts " Method: demonstrate_variable_lookup" | |
| puts " Department: #{@dept_name} (instance variable)" | |
| puts " Manager: #{@manager} (instance variable)" | |
| puts "\n📊 Ruby's Variable Search Order:" | |
| puts " 1. Local variables first: #{local_meeting_agenda}" | |
| puts " 2. Instance variables (@): Department #{@dept_name}, Manager #{@manager}" | |
| puts " 3. Class variables (@@): Budget $#{@@department_budget}" | |
| puts " 4. Global variables ($): #{$company_motto}" | |
| # Demonstrate variable shadowing (when names conflict) | |
| demonstrate_shadowing | |
| end | |
| def demonstrate_shadowing | |
| # Local variable with same name as global variable | |
| company_motto = "Local meeting motto: Focus and Execute" # Shadows the global $company_motto | |
| puts "\n👥 VARIABLE SHADOWING EXAMPLE:" | |
| puts " Local variable 'company_motto': #{company_motto}" | |
| puts " Global variable '$company_motto': #{$company_motto}" | |
| puts " (Local variable 'shadows' or hides the global one)" | |
| end | |
| def access_different_scopes | |
| puts "\n🎯 ACCESSING DIFFERENT VARIABLE SCOPES:" | |
| # Local variable | |
| current_project = "Website Redesign" | |
| puts " Local variable: #{current_project}" | |
| # Instance variable (department-specific) | |
| puts " Instance variable: #{@dept_name} department" | |
| # Class variable (company-wide department info) | |
| puts " Class variable: $#{@@department_budget} total budget" | |
| # Global variable (universal) | |
| puts " Global variable: #{$company_motto}" | |
| # What happens when we try to access a variable that doesn't exist? | |
| begin | |
| puts " Trying to access non-existent variable: #{non_existent_var}" | |
| rescue NameError => e | |
| puts " ❌ Error: #{e.message}" | |
| puts " (Ruby searched all scopes but couldn't find this variable)" | |
| end | |
| end | |
| end | |
| # Create departments and demonstrate variable lookup | |
| engineering = Department.new("Engineering", "Sarah Chen") | |
| marketing = Department.new("Marketing", "Mike Johnson") | |
| engineering.demonstrate_variable_lookup | |
| marketing.access_different_scopes | |
| # ========================================== | |
| # 6. PRACTICAL BUSINESS SCENARIOS | |
| # ========================================== | |
| puts "\n\n6. PRACTICAL BUSINESS SCENARIOS" | |
| puts "-" * 50 | |
| # Scenario 1: Multi-level business hierarchy with proper variable scoping | |
| class Corporation | |
| @@total_revenue = 0 # Class variable - company-wide revenue | |
| @@employee_count = 0 # Class variable - total employees | |
| def self.add_revenue(amount) | |
| @@total_revenue += amount | |
| end | |
| def self.hire_employee | |
| @@employee_count += 1 | |
| end | |
| def self.corporate_report | |
| puts "\n🏢 CORPORATE REPORT:" | |
| puts " Total Revenue: $#{@@total_revenue}" | |
| puts " Total Employees: #{@@employee_count}" | |
| puts " Revenue per Employee: $#{(@@total_revenue / @@employee_count.to_f).round(2)}" | |
| end | |
| end | |
| class BusinessUnit < Corporation | |
| def initialize(unit_name, initial_budget) | |
| @unit_name = unit_name # Instance variable - this unit's name | |
| @budget = initial_budget # Instance variable - this unit's budget | |
| @quarterly_sales = [] # Instance variable - this unit's sales history | |
| self.class.hire_employee # Update corporate employee count | |
| puts "🏭 Created business unit: #{@unit_name} with budget $#{@budget}" | |
| end | |
| def record_quarterly_sales(q1, q2, q3, q4) | |
| @quarterly_sales = [q1, q2, q3, q4] # Instance variable updated | |
| total_sales = @quarterly_sales.sum | |
| # Update corporate revenue (class variable) | |
| Corporation.add_revenue(total_sales) | |
| puts "\n📈 #{@unit_name} Annual Sales:" | |
| @quarterly_sales.each_with_index do |sales, index| | |
| puts " Q#{index + 1}: $#{sales}" | |
| end | |
| puts " Total: $#{total_sales}" | |
| # Local variable for performance calculation | |
| performance_rating = if total_sales > @budget * 1.2 | |
| "Excellent" | |
| elsif total_sales > @budget | |
| "Good" | |
| else | |
| "Needs Improvement" | |
| end | |
| puts " Performance: #{performance_rating} (Budget: $#{@budget})" | |
| end | |
| def unit_summary | |
| puts "\n📊 UNIT SUMMARY for #{@unit_name}:" | |
| puts " Budget: $#{@budget} (instance variable)" | |
| puts " Quarterly Sales: #{@quarterly_sales} (instance variable)" | |
| if @quarterly_sales.any? | |
| puts " Best Quarter: Q#{@quarterly_sales.index(@quarterly_sales.max) + 1} ($#{@quarterly_sales.max})" | |
| end | |
| end | |
| end | |
| # Create business units (each with their own instance variables) | |
| puts "\nCreating business units:" | |
| tech_division = BusinessUnit.new("Technology Division", 2000000) | |
| sales_division = BusinessUnit.new("Sales Division", 1500000) | |
| marketing_division = BusinessUnit.new("Marketing Division", 800000) | |
| # Record sales (updating instance and class variables) | |
| tech_division.record_quarterly_sales(450000, 520000, 480000, 610000) | |
| sales_division.record_quarterly_sales(380000, 420000, 390000, 450000) | |
| marketing_division.record_quarterly_sales(180000, 220000, 210000, 240000) | |
| # Show individual unit summaries (instance variables) | |
| tech_division.unit_summary | |
| sales_division.unit_summary | |
| # Show corporate overview (class variables) | |
| Corporation.corporate_report | |
| # ========================================== | |
| # 7. VARIABLE SCOPE BEST PRACTICES | |
| # ========================================== | |
| puts "\n\n7. VARIABLE SCOPE BEST PRACTICES" | |
| puts "-" * 50 | |
| class BestPracticesExample | |
| # Class variables for company-wide settings | |
| @@company_name = "Best Practices Corp" | |
| @@default_benefits_package = "Standard" | |
| def initialize(employee_name) | |
| @employee_name = employee_name # Instance variable for employee-specific data | |
| @hire_date = Time.now.strftime("%Y-%m-%d") | |
| @projects = [] | |
| puts "✅ #{@employee_name} hired on #{@hire_date}" | |
| end | |
| def start_project(project_name, budget) | |
| # Local variables for method-specific calculations | |
| project_start_date = Time.now.strftime("%Y-%m-%d") | |
| estimated_duration = calculate_duration(budget) # Local variable from method call | |
| # Update instance variable (employee's project list) | |
| @projects << { | |
| name: project_name, | |
| budget: budget, | |
| start_date: project_start_date, | |
| duration: estimated_duration | |
| } | |
| puts "🚀 #{@employee_name} started project: #{project_name}" | |
| puts " Budget: $#{budget}" | |
| puts " Estimated duration: #{estimated_duration} weeks" | |
| puts " Start date: #{project_start_date}" | |
| end | |
| private | |
| def calculate_duration(budget) | |
| # Local variable calculation - only exists in this method | |
| base_weeks = 4 | |
| complexity_factor = budget / 10000.0 | |
| duration = (base_weeks + complexity_factor).round | |
| [duration, 2].max # Minimum 2 weeks | |
| end | |
| public | |
| def employee_report | |
| puts "\n👤 EMPLOYEE REPORT: #{@employee_name}" | |
| puts " Company: #{@@company_name} (class variable)" | |
| puts " Hire Date: #{@hire_date} (instance variable)" | |
| puts " Benefits: #{@@default_benefits_package} (class variable)" | |
| puts " Active Projects: #{@projects.length} (instance variable)" | |
| @projects.each do |project| | |
| puts " • #{project[:name]} ($#{project[:budget]})" | |
| end | |
| end | |
| end | |
| puts "\n🎯 DEMONSTRATING BEST PRACTICES:" | |
| # Create employees with proper variable usage | |
| john = BestPracticesExample.new("John Smith") | |
| jane = BestPracticesExample.new("Jane Doe") | |
| # Each employee manages their own projects (instance variables) | |
| john.start_project("E-commerce Platform", 150000) | |
| john.start_project("Mobile App", 80000) | |
| jane.start_project("Data Analytics", 120000) | |
| jane.start_project("Security Audit", 60000) | |
| # Generate reports showing proper variable scoping | |
| john.employee_report | |
| jane.employee_report | |
| # ========================================== | |
| # 8. COMMON SCOPING MISTAKES AND SOLUTIONS | |
| # ========================================== | |
| puts "\n\n8. COMMON SCOPING MISTAKES AND SOLUTIONS" | |
| puts "-" * 50 | |
| puts "\n❌ COMMON MISTAKE #1: Confusing local and instance variables" | |
| class WrongWay | |
| def initialize(name) | |
| name = name # Wrong! This creates a local variable, not an instance variable | |
| end | |
| def get_name | |
| name # This will fail - local variable doesn't exist here | |
| rescue NameError | |
| "Name not found - local variable doesn't persist between methods" | |
| end | |
| end | |
| class RightWay | |
| def initialize(name) | |
| @name = name # Right! This creates an instance variable | |
| end | |
| def get_name | |
| @name # This works - instance variable persists across methods | |
| end | |
| end | |
| wrong_employee = WrongWay.new("Alice") | |
| right_employee = RightWay.new("Bob") | |
| puts "Wrong way result: #{wrong_employee.get_name}" | |
| puts "Right way result: #{right_employee.get_name}" | |
| puts "\n❌ COMMON MISTAKE #2: Overusing global variables" | |
| # Wrong approach - everything global | |
| $user_name = "Alice" | |
| $user_salary = 75000 | |
| $user_department = "Engineering" | |
| def wrong_employee_info | |
| puts "❌ Bad practice: #{$user_name} earns $#{$user_salary} in #{$user_department}" | |
| end | |
| # Right approach - proper encapsulation | |
| class ProperEmployee | |
| def initialize(name, salary, department) | |
| @name = name # Instance variable - belongs to this employee | |
| @salary = salary | |
| @department = department | |
| end | |
| def employee_info | |
| puts "✅ Good practice: #{@name} earns $#{@salary} in #{@department}" | |
| end | |
| end | |
| puts "\nDemonstrating global variable problems:" | |
| wrong_employee_info # Uses global variables | |
| # What happens when we need multiple employees? | |
| $user_name = "Bob" # Oops! This overwrites Alice's data | |
| $user_salary = 80000 | |
| $user_department = "Sales" | |
| wrong_employee_info # Now Alice's data is lost! | |
| puts "\nProper approach with instance variables:" | |
| alice_proper = ProperEmployee.new("Alice", 75000, "Engineering") | |
| bob_proper = ProperEmployee.new("Bob", 80000, "Sales") | |
| alice_proper.employee_info # Alice's data is safe | |
| bob_proper.employee_info # Bob's data is separate | |
| puts "\n❌ COMMON MISTAKE #3: Variable name conflicts" | |
| class VariableConflicts | |
| @@company_bonus = 5000 # Class variable | |
| def initialize(name) | |
| @name = name | |
| @company_bonus = 3000 # Instance variable with same name - confusing! | |
| end | |
| def show_bonus_confusion | |
| company_bonus = 1000 # Local variable with same name - very confusing! | |
| puts "🤔 CONFUSING VARIABLE NAMES:" | |
| puts " Local variable 'company_bonus': $#{company_bonus}" | |
| puts " Instance variable '@company_bonus': $#{@company_bonus}" | |
| puts " Class variable '@@company_bonus': $#{@@company_bonus}" | |
| puts " This is confusing and error-prone!" | |
| end | |
| def clear_naming_example | |
| monthly_individual_bonus = 1000 # Clear local variable name | |
| puts "\n✅ CLEAR VARIABLE NAMES:" | |
| puts " Local: monthly_individual_bonus = $#{monthly_individual_bonus}" | |
| puts " Instance: @company_bonus = $#{@company_bonus}" | |
| puts " Class: @@company_bonus = $#{@@company_bonus}" | |
| puts " Much clearer what each variable represents!" | |
| end | |
| end | |
| confused_employee = VariableConflicts.new("Charlie") | |
| confused_employee.show_bonus_confusion | |
| confused_employee.clear_naming_example | |
| # ========================================== | |
| # 9. SCOPE AND MEMORY MANAGEMENT | |
| # ========================================== | |
| puts "\n\n9. SCOPE AND MEMORY MANAGEMENT" | |
| puts "-" * 50 | |
| puts "\n💾 MEMORY IMPLICATIONS OF VARIABLE SCOPES:" | |
| def demonstrate_memory_usage | |
| puts "\n🔍 Memory and Scope Relationship:" | |
| # Local variables - cleaned up when method ends | |
| large_local_data = Array.new(1000) { rand(1000) } | |
| puts " ✅ Local variables: Automatically cleaned up when method ends" | |
| puts " Created array with #{large_local_data.length} elements" | |
| # The large_local_data will be garbage collected when this method ends | |
| return "Local variables cleaned up automatically" | |
| end | |
| class MemoryExample | |
| def initialize | |
| # Instance variables - live as long as the object exists | |
| @persistent_data = Array.new(500) { rand(1000) } | |
| @@class_shared_data ||= Array.new(100) { rand(1000) } # Class variable | |
| puts " ⚠️ Instance variables: Live as long as the object exists" | |
| puts " ⚠️ Class variables: Live for entire program duration" | |
| end | |
| def add_more_data | |
| # This adds to the instance variable - increases memory usage | |
| @persistent_data += Array.new(100) { rand(1000) } | |
| puts " 📈 Instance variable grew to #{@persistent_data.length} elements" | |
| end | |
| def create_temporary_calculation | |
| # Local variables for calculations | |
| temp_results = @persistent_data.map { |x| x * 2 } | |
| final_result = temp_results.sum | |
| # temp_results will be cleaned up when method ends | |
| puts " 🧮 Temporary calculation completed: #{final_result}" | |
| puts " Temporary array will be garbage collected" | |
| final_result | |
| end | |
| end | |
| # Demonstrate memory management | |
| result = demonstrate_memory_usage | |
| puts "Result: #{result}" | |
| memory_example = MemoryExample.new | |
| memory_example.add_more_data | |
| memory_example.create_temporary_calculation | |
| puts "\n💡 MEMORY BEST PRACTICES:" | |
| puts " • Use local variables for temporary calculations" | |
| puts " • Use instance variables for object-specific data" | |
| puts " • Use class variables sparingly (they never get cleaned up)" | |
| puts " • Avoid global variables (they live forever and pollute global namespace)" | |
| # ========================================== | |
| # 10. REAL-WORLD BUSINESS APPLICATION | |
| # ========================================== | |
| puts "\n\n10. REAL-WORLD BUSINESS APPLICATION" | |
| puts "-" * 50 | |
| # Complete business system demonstrating proper variable scoping | |
| $tax_rate = 0.08 # Global - universal tax rate | |
| $currency = "USD" # Global - universal currency | |
| class InvoiceSystem | |
| @@next_invoice_number = 1000 # Class variable - shared invoice numbering | |
| @@total_invoices_generated = 0 # Class variable - company statistics | |
| def initialize(company_name, address) | |
| @company_name = company_name # Instance variable - this company's info | |
| @company_address = address | |
| @invoices = [] # Instance variable - this company's invoices | |
| puts "🏢 Invoice system initialized for #{@company_name}" | |
| end | |
| def create_invoice(client_name, items) | |
| # Local variables for this specific invoice | |
| invoice_number = @@next_invoice_number | |
| invoice_date = Time.now.strftime("%Y-%m-%d") | |
| # Calculate totals using local variables | |
| subtotal = items.sum { |item| item[:quantity] * item[:price] } | |
| tax_amount = subtotal * $tax_rate | |
| total_amount = subtotal + tax_amount | |
| # Create invoice hash (local variable) | |
| invoice = { | |
| number: invoice_number, | |
| date: invoice_date, | |
| client: client_name, | |
| items: items, | |
| subtotal: subtotal, | |
| tax: tax_amount, | |
| total: total_amount | |
| } | |
| # Update instance and class variables | |
| @invoices << invoice | |
| @@next_invoice_number += 1 | |
| @@total_invoices_generated += 1 | |
| puts "\n📄 INVOICE ##{invoice_number} CREATED" | |
| puts " Company: #{@company_name}" | |
| puts " Client: #{client_name}" | |
| puts " Date: #{invoice_date}" | |
| puts " Items: #{items.length}" | |
| puts " Subtotal: #{format_currency(subtotal)}" | |
| puts " Tax (#{($tax_rate * 100).to_i}%): #{format_currency(tax_amount)}" | |
| puts " Total: #{format_currency(total_amount)}" | |
| invoice_number | |
| end | |
| def company_report | |
| # Access instance variables for company-specific data | |
| total_revenue = @invoices.sum { |inv| inv[:total] } | |
| average_invoice = @invoices.length > 0 ? total_revenue / @invoices.length : 0 | |
| puts "\n📊 COMPANY REPORT: #{@company_name}" | |
| puts " Address: #{@company_address}" | |
| puts " Invoices Generated: #{@invoices.length}" | |
| puts " Total Revenue: #{format_currency(total_revenue)}" | |
| puts " Average Invoice: #{format_currency(average_invoice)}" | |
| end | |
| def self.system_statistics | |
| # Access class variables for system-wide statistics | |
| puts "\n📈 SYSTEM STATISTICS:" | |
| puts " Total Invoices Generated: #{@@total_invoices_generated}" | |
| puts " Next Invoice Number: #{@@next_invoice_number}" | |
| puts " Global Tax Rate: #{($tax_rate * 100).to_i}%" | |
| puts " Currency: #{$currency}" | |
| end | |
| private | |
| def format_currency(amount) | |
| # Local variable for formatting | |
| formatted = "%.2f" % amount | |
| "$#{formatted} #{$currency}" | |
| end | |
| end | |
| # Create multiple companies (each with their own instance variables) | |
| puts "\nSetting up invoice systems:" | |
| tech_company = InvoiceSystem.new("Tech Solutions Inc", "123 Innovation Drive") | |
| consulting_firm = InvoiceSystem.new("Business Consultants LLC", "456 Strategy Street") | |
| # Generate invoices (local variables in each method call) | |
| puts "\nGenerating invoices:" | |
| tech_items = [ | |
| { description: "Web Development", quantity: 1, price: 5000 }, | |
| { description: "Database Setup", quantity: 1, price: 2000 }, | |
| { description: "Testing", quantity: 20, price: 100 } | |
| ] | |
| consulting_items = [ | |
| { description: "Strategy Consultation", quantity: 40, price: 150 }, | |
| { description: "Market Analysis", quantity: 1, price: 3000 } | |
| ] | |
| tech_company.create_invoice("Acme Corp", tech_items) | |
| consulting_firm.create_invoice("Global Industries", consulting_items) | |
| tech_company.create_invoice("StartupXYZ", [ | |
| { description: "MVP Development", quantity: 1, price: 8000 } | |
| ]) | |
| # Generate reports (showing different variable scopes) | |
| tech_company.company_report # Uses instance variables | |
| consulting_firm.company_report # Uses different instance variables | |
| InvoiceSystem.system_statistics # Uses class variables and globals | |
| puts "\n" + "=" * 60 | |
| puts "KEY CONCEPTS SUMMARY" | |
| puts "=" * 60 | |
| puts "\n🏢 LOCAL VARIABLES (lowercase_name):" | |
| puts " • Like department-level information" | |
| puts " • Only exist within their method/block" | |
| puts " • Automatically cleaned up when scope ends" | |
| puts " • Use for: temporary calculations, method parameters" | |
| puts "\n👤 INSTANCE VARIABLES (@name):" | |
| puts " • Like employee personal information" | |
| puts " • Belong to specific object instances" | |
| puts " • Live as long as the object exists" | |
| puts " • Use for: object-specific data, state that persists" | |
| puts "\n🏢 CLASS VARIABLES (@@name):" | |
| puts " • Like company-wide policies" | |
| puts " • Shared by all instances of a class" | |
| puts " • Live for entire program duration" | |
| puts " • Use for: shared counters, company-wide settings" | |
| puts "\n🌍 GLOBAL VARIABLES ($name):" | |
| puts " • Like industry-wide standards" | |
| puts " • Accessible from anywhere in the program" | |
| puts " • Live for entire program duration" | |
| puts " • Use sparingly for: universal constants, system-wide settings" | |
| puts "\n🎯 BUSINESS TAKEAWAYS:" | |
| puts " • Choose scope based on who needs access to the information" | |
| puts " • Local = temporary work, Instance = personal data" | |
| puts " • Class = company policies, Global = industry standards" | |
| puts " • Proper scoping makes code organized, secure, and maintainable" | |
| puts " • When in doubt, use the most restrictive scope that works" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment