S/W Design and Architecture

Template Method Pattern

Objectives

During this activity:

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

This activity must be developed in the pre-assigned teams of two.

  1. Create a directory called templatemethod and a subdirectory src within it. Inside the src folder create three files called: table_generator.rb, table_generator_test.rb, and student.rb.

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

    # Template Method Pattern
    # Date: 03-Mar-2022
    # Authors:
    #          A01160611 Thursday Rubinstein 
    #          A01777771 Stephen Strange
    

    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 (CSV stands for Comma-separated values) 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, add 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 table_generator_test.rb.
    # File name: table_generator_test.rb
    
    require 'minitest/autorun'
    require 'table_generator'
    require 'student'
    
    class TableGeneratorTest < Minitest::Test
    
      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,
                                     "Damien 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,Damien 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>Damien 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|Damien Thorn|66|66|66|66\n" +
          "|718|Manjula Nahasapeemapetilon|53|72|88|71\n" +
          "|==========\n",
          AsciiDocTableGenerator.new(@headerStudents,
                                     @dataStudents).generate
      end
    
    end
    
  3. Write and generate your program’s documentation as described in: Documenting Ruby Programs.

Deliverables

Create a compressed tarball file with the full contents of the templatemethod directory (including the generated HTML documentation in the doc subdirectory). Call this file templatemethod.tgz. From a terminal, you can use the following command to create this file (make sure to run it at the same level where the templatemethod folder resides):

tar czf templatemethod.tgz templatemethod

Upload Instructions

To deliver the templatemethod.tgz file, please provide the following information:

Request PIN

Only one team member needs to upload the file.

Due date is Thursday, March 3.

Evaluation

This activity will be evaluated using the following criteria:

50% Implementation of program requirements.
50% Documentation.
1 The program and/or documentation was plagiarized.