You are here:   ArielOrtiz.com > Software Design and Architecture > Lab 2: Template Method

Lab 2: Template Method

Objectives

During this lab session:

This activity helps students develop the following skills, values and attitudes: ability to analyze and synthesize, capacity for identifying and solving problems, and efficient use of computer systems.

Activity Description

IMPORTANT NOTE: The lab activities can be developed individually or in pairs. The lab report must be developed individually.

  1. Create a folder called templatemethod. Inside this folder, create three files called: table_generator.rb, test_table_generator.rb, and student.rb.

    All three Ruby source files must start with a comment containing the lab's title, date, and the authors' personal information. For example:

    # Lab 2: Template Method
    # Date: 25-Jan-2012
    # Authors:
    # 456654  Thursday Rubinstein 
    # 1160611 Anthony Stark

    The initial content of the table_generator.rb and student.rb files should be as follows. Study them carefully so you understand how they work.

    # File name: table_generator.rb
    
    class TableGenerator
      
      def initialize(header, data)
        @header = header
        @data = data    
      end
      
      def generate
        generate_header_row + (@data.map {|x| generate_row(x)}).join
      end
      
      def generate_header_row    
        (@header.map {|x| generate_header_item(x)}).join
      end
      
      def generate_item(item)
        item
      end
      
      def generate_row(row)
        (row.map {|x| generate_item(x)}).join
      end
      
      def generate_header_item(item)
        item
      end
    end
    
    class CSVTableGenerator < TableGenerator
      
      def generate_row(row)
        "#{(row.map {|x| generate_item(x)}).join(',')}\n"
      end
      
      def generate_header_row
        generate_row(@header)
      end
        
    end
    
    # File name: student.rb
    
    class Student
      
      include Enumerable
      # Note: This class does not support the max, min, or sort methods.
      
      def initialize(id, name, grades)
        @id = id
        @name = name
        @grades = grades    
      end
      
      def inspect
        "Student(#{@id}, #{@name.inspect})"
      end
      
      def grade_average
        @grades.inject(:+)/@grades.size
      end
      
      def each &block
        yield @id
        yield @name
        @grades.each(&block)
        yield grade_average
      end
      
    end

    The TableGenerator and its subclass CSVTableGenerator are an implementation of the Template Method pattern. Given some tabular data, they allow generating tables in different kinds of text formats. The Student class will be used when testing.

  2. In the table_generator.rb source file, write the following classes: HTMLTableGenerator and AsciiDocTableGenerator. These classes must extend TableGenerator and override the appropriate methods so that the following unit tests work as expected. Place the test class in the source file called test_table_generator.rb.
    # File name: test_table_generator.rb
    
    require 'test/unit'
    require 'table_generator'
    require 'student'
    
    class TableGeneratorTest < Test::Unit::TestCase
      
      def setup
        @headerEmpty = []
        @dataEmpty = []
        
        @headerNums = %w{Snap Crackle Pop}
        @dataNums = [[10, 20, 30],
                    [12, 64, 13],
                    [34, 11, 29],
                    [99, 15, 34]]
        
        @headerStudents = %w{id name grade1 grade2 grade3 average}
        @dataStudents = [Student.new(123, "Selma Bouvier", [71, 84, 89]),
                         Student.new(241, "Carl Carlson", [78, 85, 90]),
                         Student.new(299, "Todd Flanders", [67, 71, 77]),
                         Student.new(311, "Barney Gumble", [24, 18, 35]),
                         Student.new(427, "Edna Krabappel", [92, 95, 99]),
                         Student.new(666, "Damian Thorn", [66, 66, 66]),
                         Student.new(718, "Manjula Nahasapeemapetilon", [53, 72, 88])]
      end
      
      def test_CSVTableGenerator    
        assert_equal \
          "Snap,Crackle,Pop\n" +
          "10,20,30\n" +
          "12,64,13\n" +
          "34,11,29\n" +
          "99,15,34\n",
          CSVTableGenerator.new(@headerNums, @dataNums).generate
        assert_equal \
          "id,name,grade1,grade2,grade3,average\n" +
          "123,Selma Bouvier,71,84,89,81\n" +
          "241,Carl Carlson,78,85,90,84\n" +
          "299,Todd Flanders,67,71,77,71\n" +
          "311,Barney Gumble,24,18,35,25\n" +
          "427,Edna Krabappel,92,95,99,95\n" +
          "666,Damian Thorn,66,66,66,66\n" +
          "718,Manjula Nahasapeemapetilon,53,72,88,71\n",
          CSVTableGenerator.new(@headerStudents, @dataStudents).generate      
      end
    
      def test_HTMLTableGenerator    
        assert_equal \
          "<table>\n" +
          "<tr><th>Snap</th><th>Crackle</th><th>Pop</th></tr>\n" +
          "<tr><td>10</td><td>20</td><td>30</td></tr>\n" +
          "<tr><td>12</td><td>64</td><td>13</td></tr>\n" +
          "<tr><td>34</td><td>11</td><td>29</td></tr>\n" +
          "<tr><td>99</td><td>15</td><td>34</td></tr>\n" +
          "</table>\n",
          HTMLTableGenerator.new(@headerNums, @dataNums).generate
        assert_equal \
          "<table>\n" +
          "<tr><th>id</th><th>name</th><th>grade1</th>" +
          "<th>grade2</th><th>grade3</th><th>average</th></tr>\n" +
          "<tr><td>123</td><td>Selma Bouvier</td><td>71</td>" +
          "<td>84</td><td>89</td><td>81</td></tr>\n" +
          "<tr><td>241</td><td>Carl Carlson</td><td>78</td>" +
          "<td>85</td><td>90</td><td>84</td></tr>\n" +
          "<tr><td>299</td><td>Todd Flanders</td><td>67</td>" +
          "<td>71</td><td>77</td><td>71</td></tr>\n" +
          "<tr><td>311</td><td>Barney Gumble</td><td>24</td>" +
          "<td>18</td><td>35</td><td>25</td></tr>\n" +
          "<tr><td>427</td><td>Edna Krabappel</td><td>92</td>" +
          "<td>95</td><td>99</td><td>95</td></tr>\n" +
          "<tr><td>666</td><td>Damian Thorn</td><td>66</td>" +
          "<td>66</td><td>66</td><td>66</td></tr>\n" +
          "<tr><td>718</td><td>Manjula Nahasapeemapetilon</td><td>53</td>" +
          "<td>72</td><td>88</td><td>71</td></tr>\n" +
          "</table>\n",
          HTMLTableGenerator.new(@headerStudents, @dataStudents).generate
      end
      
      def test_AsciiDocTableGenerator    
        assert_equal \
          "[options=\"header\"]\n" +
          "|==========\n" +
          "|Snap|Crackle|Pop\n" +
          "|10|20|30\n" +
          "|12|64|13\n" +
          "|34|11|29\n" +
          "|99|15|34\n" +
          "|==========\n",
          AsciiDocTableGenerator.new(@headerNums, @dataNums).generate    
        assert_equal \
          "[options=\"header\"]\n" +
          "|==========\n" +
          "|id|name|grade1|grade2|grade3|average\n" +
          "|123|Selma Bouvier|71|84|89|81\n" +
          "|241|Carl Carlson|78|85|90|84\n" +
          "|299|Todd Flanders|67|71|77|71\n" +
          "|311|Barney Gumble|24|18|35|25\n" +
          "|427|Edna Krabappel|92|95|99|95\n" +
          "|666|Damian Thorn|66|66|66|66\n" +
          "|718|Manjula Nahasapeemapetilon|53|72|88|71\n" +
          "|==========\n",
          AsciiDocTableGenerator.new(@headerStudents, @dataStudents).generate
      end
    end
    

Deliverables

To hand in your individual lab work, follow these instructions.

Due date is Tuesday, January 31.

Evaluation

This activity will be evaluated using the following criteria:

50% Implementation of functional requirements.
50% Lab report.
DA The program and/or report was plagiarized.