how many lines of custom ABAP code are inside your system?
Updated on December 16, 2009: How many lines of custom ABAP code are inside your system? – Part2
Updated on February 5, 2009: out-of-scope section was added
After the Simple ABAP Benchmark , I’m glad to share here in SDN another simple ABAP tool to monitor your system, it is called ZSDN_simple_ABAP_SLOC_COUNT.
Download
The utility can be downloaded as Slinkee (SAPLINK) from the project home page http://code.google.com/p/abapsloc/ or create a report in SE38 and paste the following code.
Execute it and read the number of lines at the end of the list.
SLOC Reference
Source lines of code (SLOC) is just an indicator, I don’t want to give it too much relevance but it can be useful for example to estimate the upgrade effort or to evaluate the amount of work allocated for each of yours packages.
You can compare your system with well known software (source Wikipedia):
-
Windows XP: 45 million lines of code
-
Windows Vista: 50 million lines of code (see here)
-
Mac OS: 86 million lines of code ( see here)
and also with the standard SAP system:
-
SAP (ABAP): 238 million lines of ABAP (see here)
Let’s build up our SDN database
To compare apples with apples, I prepared a public Google spreadsheet where you can publish the SLOC of your ABAP system. It’s not suggested to specify your company but it could be interesting to know the country (where the system is maintained) and the year of the first implementation.
The form to update the spreadsheet is available here
The spreadsheet is available here
Additional notes
The tool has been developed during our free time from work by Andrea Olivieri (he is really an ABAP Guru) and myself; please note that we had no time to optimize it.
We exclude ABAP generated by special frameworks (e.g. Report writer, SAP Query, Web Dynpro, LSMW, …) filtering by Source System, Owner and Package.
Supported releases
SAP ECC 6.0
Out-of-scope
This utility doesn’t take into account the code contained in the following objects:
-
BSP
-
Adobe Form/SMARTFORMs/SAPScript
-
XSLT
first of all thanks for sharing this nice program.
I just have one comment. You've already partly mentioned it in your blog. It does not make any sense to compare results from your neat program with SLOC of Windows or Mac OS X. The problem is in different programing languages. Some languages require more lines than others. Another problem is in application type. For example your program has only 361 lines. But something similar written in C would take much much more.
It would be better to know for example all packages related to MM module and then get SLOC for MM.
Cheers
here are some hints that apply to different scenarios:
- I'm working for a company with a simple Landscape (e.g one SAP system): you could compare packages or developers
- I'm working for a group with a complex Landscape (e.g an SAP system per company/region): you could compare systems
- I'm working as an SAP consultant: you could compare different installations
- last but not least, are you a member of SDN: as reported above in the chapter "Let's build up our SDN database", compare with the SDN database (hoping it will be populated)
Will you the first using the public form https://spreadsheets.google.com/viewform?key=pvnwnKIJiJ7hhPUrVGxpxNw to populate the database?
Sergio
We will see if it will be possible to include also BSP...
For the moment I added an out-of-scope section...
Sergio
Transaction SE38 should be used...
Sergio
Thanks
Diego
as soon as we will have access to a R4.7 system we will try to adopt the utility. Probably we'll comment out the analysis related to ABAP CLASSes (they were not so used in R4.7).
Sergio
thank you. 🙂
I quickly adapted the utility to the R4.7.
Replace the contents of the routine FORM ALV and add those other routines: FORM SET_ORDER; FORM FIELDCAT2.
*&---------------------------------------------------------------------*
*& Form alv
*&---------------------------------------------------------------------*
* Created by ALVRobot.com.ar; Special thanks to Gabriel Jenik
*----------------------------------------------------------------------*
FORM alv.
TYPE-POOLS: slis.
* ALV required data objects.
DATA: w_title TYPE lvc_title,
w_repid TYPE syrepid,
w_comm TYPE slis_formname,
w_status TYPE slis_formname,
x_layout TYPE slis_layout_alv,
t_event TYPE slis_t_event,
t_fieldcat TYPE slis_t_fieldcat_alv,
t_sort TYPE slis_t_sortinfo_alv.
REFRESH t_fieldcat.
REFRESH t_event.
REFRESH t_sort.
CLEAR x_layout.
CLEAR w_title.
* Field Catalog
PERFORM set_fieldcat2 USING:
1 'DEVCLASS' 'DEVCLASS' 'TADIR' space space space space space space space space space space space space t_fieldcat ,
2 'NAME' 'NAME' 'TRDIR' space space space space space space space space space space space space t_fieldcat ,
3 'OBJECT' 'OBJECT' 'TADIR' space space space space space space space space space space space space t_fieldcat ,
4 'SRCSYSTEM' 'SRCSYSTEM' 'TADIR' space space space space space space space space space space space space t_fieldcat ,
5 'AUTHOR' 'AUTHOR' 'TADIR' space space space space space space space space space space space space t_fieldcat ,
6 'SUBC' 'SUBC' 'TRDIR' space space space space space space space space space space space space t_fieldcat ,
7 'SLOC' 'SLOC' space space space space space space space space space space space space 'X' t_fieldcat .
* Layout
x_layout-zebra = 'X'.
w_repid = sy-repid.
PERFORM set_order USING 'DEVCLASS' 'IT_DATA' 'X' space 'X' t_sort.
PERFORM set_order USING 'NAME' 'IT_DATA' 'X' space space t_sort.
* Displays the ALV grid
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = w_repid
it_fieldcat = t_fieldcat
is_layout = x_layout
it_sort = t_sort
i_save = 'X'
it_events = t_event
TABLES
t_outtab = t_repository
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM. "alv
*&------------------------------------------------------------------*
*& Form set_order
*&------------------------------------------------------------------*
* Adds an entry to the order table.
*-------------------------------------------------------------------*
FORM set_order USING p_fieldname p_tabname p_up p_down p_subtot
t_sort TYPE slis_t_sortinfo_alv.
DATA: x_sort TYPE slis_sortinfo_alv.
CLEAR x_sort.
x_sort-fieldname = p_fieldname.
x_sort-tabname = p_tabname.
x_sort-up = p_up.
x_sort-down = p_down.
x_sort-subtot = p_subtot.
APPEND x_sort TO t_sort.
ENDFORM. "set_order
*&------------------------------------------------------------------*
*& Form set_fieldcat2
*&------------------------------------------------------------------*
FORM set_fieldcat2 USING
p_colpos p_fieldname p_ref_fieldname p_ref_tabname
p_outputlen p_noout
p_seltext_m p_seltext_l p_seltext_s p_reptext_ddic p_ddictxt
p_hotspot p_showasicon p_checkbox p_edit
p_dosum
t_fieldcat TYPE slis_t_fieldcat_alv.
DATA: wa_fieldcat TYPE slis_fieldcat_alv.
CLEAR wa_fieldcat.
* General settings
wa_fieldcat-fieldname = p_fieldname.
wa_fieldcat-col_pos = p_colpos.
wa_fieldcat-no_out = p_noout.
wa_fieldcat-hotspot = p_hotspot.
wa_fieldcat-checkbox = p_checkbox.
wa_fieldcat-icon = p_showasicon.
wa_fieldcat-do_sum = p_dosum.
* Set reference fieldname, tablenam and rollname.
* If p_ref_tabname is not given, the ref_fieldname given
* is a data element.
* If p_ref_tabname is given, the ref_fieldname given is a
* field of a table.
* In case ref_fieldname is not given,
* it is copied from the fieldname.
IF p_ref_tabname IS INITIAL.
wa_fieldcat-rollname = p_ref_fieldname.
ELSE.
wa_fieldcat-ref_tabname = p_ref_tabname.
IF p_ref_fieldname EQ space.
wa_fieldcat-ref_fieldname = wa_fieldcat-fieldname.
ELSE.
wa_fieldcat-ref_fieldname = p_ref_fieldname.
ENDIF.
ENDIF.
* Set output length.
IF NOT p_outputlen IS INITIAL.
wa_fieldcat-outputlen = p_outputlen.
ENDIF.
* Set text headers.
IF NOT p_seltext_m IS INITIAL.
wa_fieldcat-seltext_m = p_seltext_m.
ENDIF.
IF NOT p_seltext_l IS INITIAL.
wa_fieldcat-seltext_l = p_seltext_l.
ENDIF.
IF NOT p_seltext_s IS INITIAL.
wa_fieldcat-seltext_s = p_seltext_s.
ENDIF.
IF NOT p_reptext_ddic IS INITIAL.
wa_fieldcat-reptext_ddic = p_reptext_ddic.
ENDIF.
IF NOT p_ddictxt IS INITIAL.
wa_fieldcat-ddictxt = p_ddictxt.
ENDIF.
* Set as editable or not.
IF NOT p_edit IS INITIAL.
wa_fieldcat-input = 'X'.
wa_fieldcat-edit = 'X'.
ENDIF.
APPEND wa_fieldcat TO t_fieldcat.
ENDFORM. "set_fieldcat2
Hope this helps.
Andrea
A cpl of years ago this question was a contest at a company I as working. I did the measurement while my colleagues had to make the best guess. <br/>It was a 4.6c system and my measurement resulted in 85,361,427 lines of ABAP code, excluding custom development.<br/>Encountering this blog I re-run my program on an ECC6 system and it resulted in 155.388.133 lines. Almost doubled! (there's a dependency on installed components, patch level etc.. This a standard business system with few IS. No netweaver, only BI and PI plug-ins )<br/>The program I used is so simple that I add it here. You can install it and try out on your own system:<br/>--
<br/>REPORT ZABAP_COUNTER.<br/><br/> tables: trdir.<br/><br/> types: begin of ty_proginfo,<br/> program type programm,<br/> counter type i,<br/> empty type i,<br/> comment type i,<br/> source type i,<br/> end of ty_proginfo.<br/><br/> data: st_proginfo type ty_proginfo,<br/> it_proginfo type table of ty_proginfo,<br/> st_progline type ty_proginfo.<br/><br/> field-symbols: <proginfo> type ty_proginfo.<br/><br/> select-options: so_progr for trdir-name.<br/><br/> select name from trdir into table it_proginfo<br/> where name in so_progr.<br/><br/> loop at it_proginfo assigning <proginfo>.<br/> perform count_program changing <proginfo>.<br/> add: <proginfo>-counter to st_proginfo-counter,<br/> <proginfo>-empty to st_proginfo-empty,<br/> <proginfo>-comment to st_proginfo-comment,<br/> <proginfo>-source to st_proginfo-source.<br/> endloop.<br/><br/> write:/ 'Programs', 20 st_proginfo-counter,<br/> / 'Empty lines', 20 st_proginfo-empty,<br/> / 'Comment lines', 20 st_proginfo-comment,<br/> / 'Source lines', 20 st_proginfo-source.<br/><br/>*&
<br/>& Form count_program<br/>*&
<br/>FORM count_program USING p_proginfo TYPE ty_proginfo.<br/><br/> data: abaptab type standard table of string,<br/> abaplin type string.<br/><br/> read report p_proginfo-program into abaptab.<br/> check sy-subrc = 0.<br/><br/> add 1 to p_proginfo-counter.<br/><br/> loop at abaptab into abaplin.<br/> if abaplin is initial.<br/> add 1 to p_proginfo-empty.<br/> elseif abaplin(1) = ''.<br/> add 1 to p_proginfo-comment.<br/> else.<br/> add 1 to p_proginfo-source.<br/> endif.<br/> endloop.<br/><br/>ENDFORM. " count_program<br/>
<br/>It's quite simple-minded counting, but however you define SLOC (e.g. include flow-logic, or exclude generated programs) they make only small differences.<br/>When scheduling it in a job it takes about 1-2 hrs to scan the whole system.<br/>Good luck!
you also provided the version for 4.6 and 4.7 as from other requests. The select-option "so_progr" allows the filter on custom objects (Y*, Z*). We will try to downgrade our version in any case.
Slide 3 of the interesting presentation "SAP and Virtualization Some Thoughts" https://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/0005265f-e4f2-2a10-85ad-dced292c0c0d includes also Java, C, C++ and others.
As you said, it's really impressive the difference between R4.6c to SAP ECC 6.0.
ABAP OO, the new ALV, BSP, SAP Web AS, Web Dynpro for ABAP, GOS, Adobe Form and a huge number of new functionalities are there.
Sergio
thanks for submitting this useful tool to the public. This is exactly what I have been looking for.
During my first test run, I encountered one issue and one defect.
1) Issue:
Why did you choose
AND obj_name IN xauthor
along with
AND author IN xauthor
in the SELECT statement? If I ever choose an "inclusion" select option, for example "count lines of program ZTEST", it won't work, because the author won't match. Similarly "count lines of program by author GERTH" will never find any entries.
I see that it works with exclusion, but in my opinion your program will work better if you have separated select options for author and object name.
2) Defect
The lines
WHEN 'FUGR'.
CONCATENATE 'SAPL' l_repository-name INTO l_irdir-name.
do not work if namespaces are involved.
I found function module FUNCTION_INCLUDE_CONCATENATE which might do the job (only fill parameter COMPLETE_AREA).
you're right, that night we developed we (me and Andera) were a bit tired.
We'll include your suggestions soon...
Sergio
I am trying to access the google spreadsheet, but it is asking me for techedge.it user ID.
Can you please update the correct link which can be accessed.
Regards,
Atish
It should work now.
Sergio