Monday 30 July 2018

Getting comfortable using the Object-Oriented design model with ABAP – Part 5

To recap from the preceding blog, we took a program having classes with multiple responsibilities and transformed it so that each class has only a single responsibility. However, we’ve noticed after making classes flight_report, carrier_report and booking_report compliant with the Single Responsibility Principle that our changes have rendered these three classes exact duplicates of each other except for their names. Here is the source code as we left it in the previous blog:

report.
interface data_exchangeable.
  types          : row_counter    type n length 02.
  types          : email_recipient
                                  type adr6-smtp_addr.
endinterface.
class flight_records_retriever         definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of sflight.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type flight_records_retriever=>record_list
                 .
endclass.
class flight_records_retriever         implementation.
  method retrieve_records.
    select *
      into table record_stack
      from sflight
             up to row_count rows.
  endmethod.
endclass.
class carrier_records_retriever        definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of scarr.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type carrier_records_retriever=>record_list
                 .
endclass.
class carrier_records_retriever        implementation.
  method retrieve_records.
    select *
      into table record_stack
      from scarr
             up to row_count rows.
  endmethod.
endclass.
class booking_records_retriever        definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of sbook.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type booking_records_retriever=>record_list
                 .
endclass.
class booking_records_retriever        implementation.
  method retrieve_records.
    select *
      into table record_stack
      from sbook
             up to row_count rows.
  endmethod.
endclass.
class excel_spreadsheet_manager        definition
                                       final.
  public section.
    methods      : copy_table_to_excel_worksheet
                     importing
                       source_stack
                         type standard table
                       source_description
                         type string
                     raising
                       zcx_excel
                 , send_excel_via_email
                     importing
                       recipient
                         type data_exchangeable=>email_recipient
                 .
  private section.
    data         : excel          type ref to zcl_excel.
endclass.
class excel_spreadsheet_manager        implementation.
  method copy_table_to_excel_worksheet.
    constants    : first_column   type char1     value 'A'
                 .
    data         : worksheet      type ref to zcl_excel_worksheet
                 , worksheet_title
                                  type zexcel_sheet_title
                 , table_settings type zexcel_s_table_settings
                 .
    table_settings-table_style    = zcl_excel_table=>builtinstyle_medium2.
    table_settings-show_row_stripes
                                  = abap_true.
    table_settings-nofilters      = abap_true.
    table_settings-top_left_column
                                  = first_column.
    table_settings-top_left_row   = 01.
    if excel is not bound.
      create object excel.
      worksheet                   = excel->get_active_worksheet( ).
    else.
      worksheet                   = excel->add_new_worksheet( ).
    endif.
    worksheet_title               = source_description.
    worksheet->set_title( worksheet_title ).
    worksheet->bind_table(
      ip_table                    = source_stack
      is_table_settings           = table_settings
      ).
  endmethod.
  method send_excel_via_email.
    constants    : excel_file_type
                                 type string value '.xlsx'
                 , file_name_parameter
                                  type string value '&SO_FILENAME='
                 .
    data         : excel_writer   type ref to zif_excel_writer
                 , excel_as_xstring
                                  type xstring
                 , excel_as_xstring_bytecount
                                  type i
                 , excel_as_solix_stack
                                  type solix_tab
                 , mail_send_request
                                  type ref to cl_bcs
                 , mail_message   type ref to cl_document_bcs
                 , any_bcs_exception
                                  type ref to cx_bcs
                 , diagnostic     type string
                 , mail_title     type so_obj_des
                 , mail_text_stack
                                  type soli_tab
                 , mail_text_entry
                                  like line
                                    of mail_text_stack
                 , mail_attachment_subject
                                  type sood-objdes
                 , mail_attachment_bytecount
                                  type sood-objlen
                 , mail_attachment_header_stack
                                  type soli_tab
                 , mail_attachment_header_entry
                                  like line of mail_attachment_header_stack
                 , internet_email_recipient
                                  type ref to if_recipient_bcs
                 , successful_send
                                  type abap_bool
                 , file_name      type string
                 .
    " Much of the code here was lifted from method send_mail of
    " class lcl_ouput, defined in object ZDEMO_EXCEL_OUTPUTOPT_INCL:
    concatenate sy-repid          " this report name
                sy-datum          " current date
                sy-uzeit          " current time
                excel_file_type   " excel file extension
           into file_name.
    mail_title                    = file_name.
    mail_attachment_subject       = file_name.
    mail_text_entry               = 'See attachment'.
    append mail_text_entry
        to mail_text_stack.
    concatenate file_name_parameter
                file_name
           into mail_attachment_header_entry.
    append mail_attachment_header_entry
        to mail_attachment_header_stack.
    create object excel_writer type zcl_excel_writer_2007.
    excel_as_xstring              = excel_writer->write_file( excel ).
    excel_as_solix_stack          = cl_bcs_convert=>xstring_to_solix( iv_xstring = excel_as_xstring ).
    excel_as_xstring_bytecount    = xstrlen( excel_as_xstring ).
    mail_attachment_bytecount     = excel_as_xstring_bytecount.
    try.
      mail_message                = cl_document_bcs=>create_document(
                                      i_type    = 'RAW' "#EC NOTEXT
                                      i_text    = mail_text_stack
                                      i_subject = mail_title
                                      ).
      mail_message->add_attachment(
        i_attachment_type         = 'XLS' "#EC NOTEXT
        i_attachment_subject      = mail_attachment_subject
        i_attachment_size         = mail_attachment_bytecount
        i_att_content_hex         = excel_as_solix_stack
        i_attachment_header       = mail_attachment_header_stack
        ).
      mail_send_request           = cl_bcs=>create_persistent( ).
      mail_send_request->set_document( mail_message ).
      internet_email_recipient    = cl_cam_address_bcs=>create_internet_address( recipient ).
      mail_send_request->add_recipient( internet_email_recipient ).
      successful_send             = mail_send_request->send( ).
      commit work.
      if successful_send eq abap_false.
        message i500(sbcoms) with recipient.
      else.
        message s022(so).
        message 'Document ready to be sent - Check SOST' type 'I'.
      endif.
    catch cx_bcs into any_bcs_exception.
      diagnostic                  = any_bcs_exception->if_message~get_text( ).
      message diagnostic type 'I'.
    endtry.
  endmethod.
endclass.
class report                           definition
                                       abstract.
  public section.
    methods      : produce_report abstract
                     changing
                       record_stack
                         type standard table
                 .
  protected section.
    methods      : present_report
                     changing
                       record_stack
                         type standard table
                 .
endclass.
class report                           implementation.
  method present_report.
    data         : alv_report     type ref to cl_salv_table
                 .
    try.
      call method cl_salv_table=>factory
        importing
          r_salv_table            = alv_report
        changing
          t_table                 = record_stack.
    catch cx_salv_msg.
      return.
    endtry.
    alv_report->display( ).
  endmethod.
endclass.
class flight_report                    definition
                                       final
                                       inheriting from report.
  public section.
    methods      : produce_report redefinition
                 .
endclass.
class flight_report                    implementation.
  method produce_report.
    call method me->present_report
      changing
        record_stack              = record_stack.
  endmethod.
endclass.
class carrier_report                   definition
                                       final
                                       inheriting from report.
  public section.
    methods      : produce_report redefinition
                 .
endclass.
class carrier_report                   implementation.
  method produce_report.
    call method me->present_report
      changing
        record_stack              = record_stack.
  endmethod.
endclass.
class booking_report                   definition
                                       final
                                       inheriting from report.
  public section.
    methods      : produce_report redefinition
                 .
endclass.
class booking_report                   implementation.
  method produce_report.
    call method me->present_report
      changing
        record_stack              = record_stack.
  endmethod.
endclass.
class process_driver                   definition
                                       abstract
                                       final.
  public section.
    class-methods: drive_process
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                       recipient
                         type data_exchangeable=>email_recipient
                 .
endclass.
class process_driver                   implementation.
  method drive_process.
    data         : flight_report  type ref to flight_report
                 , carrier_report type ref to carrier_report
                 , booking_report type ref to booking_report
                 , excel_spreadsheet_manager
                                  type ref to excel_spreadsheet_manager
                 , flight_stack   type flight_records_retriever=>record_list
                 , carrier_stack  type carrier_records_retriever=>record_list
                 , booking_stack  type booking_records_retriever=>record_list
                 .
    create object: flight_report
                 , carrier_report
                 , booking_report
                 , excel_spreadsheet_manager
                 .
    call method flight_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = flight_stack.
    call method carrier_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = carrier_stack.
    call method booking_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = booking_stack.
    call method flight_report->produce_report changing record_stack = flight_stack.
    call method carrier_report->produce_report changing record_stack = carrier_stack.
    call method booking_report->produce_report changing record_stack = booking_stack.
    try.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = flight_stack
          source_description      = 'Flights'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = carrier_stack
          source_description      = 'Carriers'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = booking_stack
          source_description      = 'Bookings'.
    catch zcx_excel ##NO_HANDLER.
    endtry.
    call method excel_spreadsheet_manager->send_excel_via_email exporting recipient = recipient.
  endmethod.
endclass.
class email_address_resolver           definition
                                       abstract
                                       final.
  public section.
    class-methods: resolve_email_address
                     importing
                       userid
                         type syuname
                     exporting
                       email_address
                         type data_exchangeable=>email_recipient
                 .
endclass.
class email_address_resolver           implementation.
  method resolve_email_address.
    select single smtp_addr
      into email_address
      from adr6 ##WARN_OK
             inner join
           usr21 on usr21~persnumber eq adr6~persnumber
     where usr21~bname            eq userid.
  endmethod.
endclass.
  parameters     : rowcount       type data_exchangeable=>row_counter.
  parameters     : recipien       type data_exchangeable=>email_recipient.
initialization.
  call method email_address_resolver=>resolve_email_address
    exporting
      userid                      = sy-uname
    importing
      email_address               = recipien.
start-of-selection.
  call method process_driver=>drive_process
    exporting
      row_count                   = rowcount
      recipient                   = recipien.

Open your favorite ABAP editor, make a copy of this ABAP program and follow along as we apply changes to remove classes that no longer serve a purpose. For those who do not have ABAP2XLSX available at their site, replace class excel_spreadsheet_manager with the following source code:

ABAP Development, SAP ABAP Objects, SAP ABAP Study Materials, SAP ABAP Guides

class excel_spreadsheet_manager        definition
                                       final.
  public section.
    methods      : copy_table_to_excel_worksheet
                     importing
                       source_stack
                         type standard table
                       source_description
                         type string
                     raising
                       zcx_excel
                 , send_excel_via_email
                     importing
                       recipient
                         type data_exchangeable=>email_recipient
                 .
  private section.
    data         : excel          type string.
endclass.
class excel_spreadsheet_manager        implementation.
  method copy_table_to_excel_worksheet.
    data         : source_stack_lines type string.
    describe table source_stack lines source_stack_lines.
    concatenate excel
                source_stack_lines
                source_description
           into excel separated by space.
  endmethod.
  method send_excel_via_email.
    data         : message        type string.
    concatenate excel
                'would be sent to'
                recipient
           into message separated by space.
    message message type 'I'.
  endmethod.
endclass.

and include the following local exception class definition after the report statement:

class zcx_excel                        definition
                                       inheriting from cx_static_check.
endclass.

Motivation

We’ve been improving our example program with each set of changes applied, each change making it that much more resilient when subjected to subsequent maintenance efforts. When we started, classes flight_report, carrier_report and booking_report each had their own unique processing to perform. Since then we have consolidated some of this processing by having these classes inherit from superclass report, and subsequently removed code from these classes to have them comply with the Single Responsibility Principle. Accordingly, those aspects of these classes that previously distinguished themselves from each other have been eliminated, resulting in three virtually identical classes.

Removing unnecessary classes

First, change class report in the following ways:
  • Remove the qualifier abstract from its class definition, replacing this with the qualifier final.
  • Remove the produce_report method definition.
  • Remove the protected section header (this will cause the present_report method now to be defined as a public method).
When completed, the definition of the report class should look like this:

class report                           definition
                                       final.
  public section.
    methods      : present_report
                     changing
                       record_stack
                         type standard table
                 .
endclass.

At this point a syntax check will fail for class flight_report inheriting from class report, which now can have no subclasses since we’ve added the qualifier final to its class definition statement.

Next, make the following changes:
  • Remove class flight_report.
  • Remove class carrier_report.
  • Remove class booking_report.
  • In method drive_process of class process_driver, do the following:
    • Change the name of variable flight_report to report and change its type to indicate reference to report.
    • Remove the definitions for variables carrier_report and booking_report.
    • On the create object statement, change variable name flight_report to report.
    • Remove carrier_report and booking_report from the create object statement.
    • Change the call to method flight_report->produce_report to report->present_report.
    • Change the call to method carrier_report->produce_report to report->present_report.
    • Change the call to method booking_report->produce_report to report->present_report.
When completed, the code in method drive_process should look like this:

  method drive_process.
    data         : report         type ref to report
                 , excel_spreadsheet_manager
                                  type ref to excel_spreadsheet_manager
                 , flight_stack   type flight_records_retriever=>record_list
                 , carrier_stack  type carrier_records_retriever=>record_list
                 , booking_stack  type booking_records_retriever=>record_list
                 .
    create object: report
                 , excel_spreadsheet_manager
                 .
    call method flight_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = flight_stack.
    call method carrier_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = carrier_stack.
    call method booking_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = booking_stack.
    call method report->present_report changing record_stack = flight_stack.
    call method report->present_report changing record_stack = carrier_stack.
    call method report->present_report changing record_stack = booking_stack.
    try.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = flight_stack
          source_description      = 'Flights'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = carrier_stack
          source_description      = 'Carriers'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = booking_stack
          source_description      = 'Bookings'.
    catch zcx_excel ##NO_HANDLER.
    endtry.
    call method excel_spreadsheet_manager->send_excel_via_email exporting recipient = recipient.
  endmethod.

At this point a syntax check will pass again.

Executing the program at this point should prove that it still works as before.

Summary


We’ve made enough changes for now and the final image of the code looks like this:

report.
interface data_exchangeable.
  types          : row_counter    type n length 02.
  types          : email_recipient
                                  type adr6-smtp_addr.
endinterface.
class flight_records_retriever         definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of sflight.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type flight_records_retriever=>record_list
                 .
endclass.
class flight_records_retriever         implementation.
  method retrieve_records.
    select *
      into table record_stack
      from sflight
             up to row_count rows.
  endmethod.
endclass.
class carrier_records_retriever        definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of scarr.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type carrier_records_retriever=>record_list
                 .
endclass.
class carrier_records_retriever        implementation.
  method retrieve_records.
    select *
      into table record_stack
      from scarr
             up to row_count rows.
  endmethod.
endclass.
class booking_records_retriever        definition
                                       abstract
                                       final.
  public section.
    types        : record_list    type standard table of sbook.
    class-methods: retrieve_records
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                     exporting
                       record_stack
                         type booking_records_retriever=>record_list
                 .
endclass.
class booking_records_retriever        implementation.
  method retrieve_records.
    select *
      into table record_stack
      from sbook
             up to row_count rows.
  endmethod.
endclass.
class excel_spreadsheet_manager        definition
                                       final.
  public section.
    methods      : copy_table_to_excel_worksheet
                     importing
                       source_stack
                         type standard table
                       source_description
                         type string
                     raising
                       zcx_excel
                 , send_excel_via_email
                     importing
                       recipient
                         type data_exchangeable=>email_recipient
                 .
  private section.
    data         : excel          type ref to zcl_excel.
endclass.
class excel_spreadsheet_manager        implementation.
  method copy_table_to_excel_worksheet.
    constants    : first_column   type char1     value 'A'
                 .
    data         : worksheet      type ref to zcl_excel_worksheet
                 , worksheet_title
                                  type zexcel_sheet_title
                 , table_settings type zexcel_s_table_settings
                 .
    table_settings-table_style    = zcl_excel_table=>builtinstyle_medium2.
    table_settings-show_row_stripes
                                  = abap_true.
    table_settings-nofilters      = abap_true.
    table_settings-top_left_column
                                  = first_column.
    table_settings-top_left_row   = 01.
    if excel is not bound.
      create object excel.
      worksheet                   = excel->get_active_worksheet( ).
    else.
      worksheet                   = excel->add_new_worksheet( ).
    endif.
    worksheet_title               = source_description.
    worksheet->set_title( worksheet_title ).
    worksheet->bind_table(
      ip_table                    = source_stack
      is_table_settings           = table_settings
      ).
  endmethod.
  method send_excel_via_email.
    constants    : excel_file_type
                                 type string value '.xlsx'
                 , file_name_parameter
                                  type string value '&SO_FILENAME='
                 .
    data         : excel_writer   type ref to zif_excel_writer
                 , excel_as_xstring
                                  type xstring
                 , excel_as_xstring_bytecount
                                  type i
                 , excel_as_solix_stack
                                  type solix_tab
                 , mail_send_request
                                  type ref to cl_bcs
                 , mail_message   type ref to cl_document_bcs
                 , any_bcs_exception
                                  type ref to cx_bcs
                 , diagnostic     type string
                 , mail_title     type so_obj_des
                 , mail_text_stack
                                  type soli_tab
                 , mail_text_entry
                                  like line
                                    of mail_text_stack
                 , mail_attachment_subject
                                  type sood-objdes
                 , mail_attachment_bytecount
                                  type sood-objlen
                 , mail_attachment_header_stack
                                  type soli_tab
                 , mail_attachment_header_entry
                                  like line of mail_attachment_header_stack
                 , internet_email_recipient
                                  type ref to if_recipient_bcs
                 , successful_send
                                  type abap_bool
                 , file_name      type string
                 .
    " Much of the code here was lifted from method send_mail of
    " class lcl_ouput, defined in object ZDEMO_EXCEL_OUTPUTOPT_INCL:
    concatenate sy-repid          " this report name
                sy-datum          " current date
                sy-uzeit          " current time
                excel_file_type   " excel file extension
           into file_name.
    mail_title                    = file_name.
    mail_attachment_subject       = file_name.
    mail_text_entry               = 'See attachment'.
    append mail_text_entry
        to mail_text_stack.
    concatenate file_name_parameter
                file_name
           into mail_attachment_header_entry.
    append mail_attachment_header_entry
        to mail_attachment_header_stack.
    create object excel_writer type zcl_excel_writer_2007.
    excel_as_xstring              = excel_writer->write_file( excel ).
    excel_as_solix_stack          = cl_bcs_convert=>xstring_to_solix( iv_xstring = excel_as_xstring ).
    excel_as_xstring_bytecount    = xstrlen( excel_as_xstring ).
    mail_attachment_bytecount     = excel_as_xstring_bytecount.
    try.
      mail_message                = cl_document_bcs=>create_document(
                                      i_type    = 'RAW' "#EC NOTEXT
                                      i_text    = mail_text_stack
                                      i_subject = mail_title
                                      ).
      mail_message->add_attachment(
        i_attachment_type         = 'XLS' "#EC NOTEXT
        i_attachment_subject      = mail_attachment_subject
        i_attachment_size         = mail_attachment_bytecount
        i_att_content_hex         = excel_as_solix_stack
        i_attachment_header       = mail_attachment_header_stack
        ).
      mail_send_request           = cl_bcs=>create_persistent( ).
      mail_send_request->set_document( mail_message ).
      internet_email_recipient    = cl_cam_address_bcs=>create_internet_address( recipient ).
      mail_send_request->add_recipient( internet_email_recipient ).
      successful_send             = mail_send_request->send( ).
      commit work.
      if successful_send eq abap_false.
        message i500(sbcoms) with recipient.
      else.
        message s022(so).
        message 'Document ready to be sent - Check SOST' type 'I'.
      endif.
    catch cx_bcs into any_bcs_exception.
      diagnostic                  = any_bcs_exception->if_message~get_text( ).
      message diagnostic type 'I'.
    endtry.
  endmethod.
endclass.
class report                           definition
                                       final.
  public section.
    methods      : present_report
                     changing
                       record_stack
                         type standard table
                 .
endclass.
class report                           implementation.
  method present_report.
    data         : alv_report     type ref to cl_salv_table
                 .
    try.
      call method cl_salv_table=>factory
        importing
          r_salv_table            = alv_report
        changing
          t_table                 = record_stack.
    catch cx_salv_msg.
      return.
    endtry.
    alv_report->display( ).
  endmethod.
endclass.
class process_driver                   definition
                                       abstract
                                       final.
  public section.
    class-methods: drive_process
                     importing
                       row_count
                         type data_exchangeable=>row_counter
                       recipient
                         type data_exchangeable=>email_recipient
                 .
endclass.
class process_driver                   implementation.
  method drive_process.
    data         : report         type ref to report
                 , excel_spreadsheet_manager
                                  type ref to excel_spreadsheet_manager
                 , flight_stack   type flight_records_retriever=>record_list
                 , carrier_stack  type carrier_records_retriever=>record_list
                 , booking_stack  type booking_records_retriever=>record_list
                 .
    create object: report
                 , excel_spreadsheet_manager
                 .
    call method flight_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = flight_stack.
    call method carrier_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = carrier_stack.
    call method booking_records_retriever=>retrieve_records
      exporting
        row_count                 = row_count
      importing
        record_stack              = booking_stack.
    call method report->present_report changing record_stack = flight_stack.
    call method report->present_report changing record_stack = carrier_stack.
    call method report->present_report changing record_stack = booking_stack.
    try.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = flight_stack
          source_description      = 'Flights'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = carrier_stack
          source_description      = 'Carriers'.
      call method excel_spreadsheet_manager->copy_table_to_excel_worksheet
        exporting
          source_stack            = booking_stack
          source_description      = 'Bookings'.
    catch zcx_excel ##NO_HANDLER.
    endtry.
    call method excel_spreadsheet_manager->send_excel_via_email exporting recipient = recipient.
  endmethod.
endclass.
class email_address_resolver           definition
                                       abstract
                                       final.
  public section.
    class-methods: resolve_email_address
                     importing
                       userid
                         type syuname
                     exporting
                       email_address
                         type data_exchangeable=>email_recipient
                 .
endclass.
class email_address_resolver           implementation.
  method resolve_email_address.
    select single smtp_addr
      into email_address
      from adr6 ##WARN_OK
             inner join
           usr21 on usr21~persnumber eq adr6~persnumber
     where usr21~bname            eq userid.
  endmethod.
endclass.
  parameters     : rowcount       type data_exchangeable=>row_counter.
  parameters     : recipien       type data_exchangeable=>email_recipient.
initialization.
  call method email_address_resolver=>resolve_email_address
    exporting
      userid                      = sy-uname
    importing
      email_address               = recipien.
start-of-selection.
  call method process_driver=>drive_process
    exporting
      row_count                   = rowcount
      recipient                   = recipien.

Despite having introduced class inheritance with previous changes, the changes applied here have now removed the use of any inheritance, an exquisite example of how continually improving the code also results in its simplification.

1 comment:

  1. very nice concpt thanks for sharing getting-comfortable-using-object topic sap hr abap training

    ReplyDelete