Batman Syndrome of Freelancers

At some point, many freelance consultants consider hiring a junior consultant. The idea is to train him/her, and send him/her to low priority clients. The assumption is; low priority clients would accept the junior (as Robin) just because the freelancer has a brand name (as Batman).

However, this assumption often fails.

Have you seen anyone calling Robin without Batman? No. Exceptions aside; people call Batman, and they could accept Robin as a sidekick only if Batman is present as well.

Batman may consider a client as “low priority”, but the client considers its own business as “high priority”. Therefore; if they call Batman, they want Batman. They often won’t accept an unaccompanied Robin. It is really hard to convince clients to accept Robin as a regular consultant just because Batman has a name.

This has a psychological aspect as well: They will continuously compare Robin to Batman, and assume Robin to be a character lesser than he/she really is.

Solution?

My initial suggestion is to make a schedule where Batman & Robin can go to projects mostly together. If both of them are present at the client site 3 days/week, the client might be willing to accept an unaccompanied Robin at the 4th day; assuming that Robin’s activities are transparent, rate is agreeable and he/she will add reasonable value to the project.

If you can find a position where one of your clients need a junior consultant, this would be a rare opportunity to market Robin! If the trust of the client is obtained, promising that Batman would jump in on critical occasions would increase the chance of a deal.

In any case, I would suggest premeditating on possible positions for Robin before taking any costly action.

Some big consultancy companies have the tendency to showcase “Batman”s during the sales process and send “Robin”s to the actual project.

This is a different case though. They are selling projects over the brand and image of a company, not a person. The client can request a change of certain consultants any time, and they can force the consultancy company to call-in “Batman”s in case a significant risk surfaces. Therefore, clients are relatively comfortable accepting mid-level team members of a big company.

Another important aspect is; decision makers feel more comfortable when they select a big brand for their SAP project (despite the mediocre CV’s). If the project fails, the manager can save his/her rear end by telling that they made the best decision they could by picking the biggest name on the market. Picking a boutique set of freelancers means that some manager takes full responsibility. Smart managers make a mixture of a big company + Batman-level freelancers though.

In any case; big players can market Robins due to such factors. It doesn’t mean that a singular Batman can pull off the same thing. It is possible, but not as easy & common.

SAP GUI For Java Connection Strings

A question I get often is about the way I connect to SAP ECC from my Mac.

Obviously, many users prefer to install Windows to their Macbooks and run SAP GUI For Windows over it.

However; SAP has an alternative less known GUI for Linux / Mac systems: SAP GUI For Java. You can download it from http://service.sap.com for free using an S-user, install it to your Mac like a regular application and connect to any SAP ECC system. No need to install Windows at all.

The way you define a new SAP Connection in SAP GUI For Java differs slightly from SAP GUI For Windows. Let’s assume that you have the following connection information:

  • Address: 10.1.3.40
  • System No: 02

In SAP GUI For Java, you need to get to the “Advanced” tab, click “Expert mode” and enter the following connection string:

conn=/H/10.1.3.40/S/3202

Obviously, the address goes between /H/ and /S/ and the system number goes to the end of the string. If your system ID is 00, you need to enter 3200. If your system ID is 07, you need to enter 3207. In our case, your system ID is 02 so you need to enter 3202.

That’s all there is! Using this connection string, you should be good to go.

Your connection string can contain additional parameters; such as your user name, client number, etc. Here are some sample connection strings:

conn=/H/sapsrv/S/3204&jenc=MacTurkish&jloc=tr&cpg=1607&clnt=100&user=kerem

Here are some sample connection strings going over routers (IP’s changed for security reasons):

conn=/H/88.249.244.45/H/10.0.0.5/S/3200

conn=/H/78.186.178.12/W/golive2013/H/192.168.2.10/S/3200
The only disadvantage of SAP GUI For Java is for ABAP programmers: Smartform designer, Workflow tools and graphical screen designer tools are Windows-only and won’t run under SAP GUI For Java. Personally, I have a casual Windows installation with SAP GUI for Windows living under VMWare Fusion. Whenever I need to use one of those tools (maybe once a month); I run Windows inside the virtual machine without leaving Mac OS, get my job done, shut down Windows and continue working on the Mac with SAP GUI For Java.

Quick SAP Tip: Get Rid of Stuck Truck Icon in STMS

In case SAP thinks that some transport requests in STMS are still imported and keeps displaying the truck icon next to them, you might get frustrated.

The solution is simple though: Just delete the corresponding entries in table TPSTAT, and you are good to go.

This is a risky approach, though. If the requests are actually being transported, removing them from TPSTAT might trigger some unpredictable behaviour. If you are 100% sure that TP is doing nothing about them, you might try this little hack.

ABAP Tip: Converting Function Module Exceptions to Exception Classes

1464-ppt

Although function modules belong to the era of procedural programming, we all need to use them from time to time. While most BAPI’s usually return error messages in a clean internal table format, many other function modules return classical exceptions.

If you are calling a function within a class method, you might have a hard time converting those classical exceptions to class based exceptions – meaning exception classes.

I have written an exception class which automatically converts any function module exception to a class based exception. Here is the source code:

CLASS zcx_bc_function_subrc DEFINITION
 PUBLIC
 INHERITING FROM cx_static_check
 FINAL
 CREATE PUBLIC .

 PUBLIC SECTION.

 INTERFACES if_t100_message .

 CONSTANTS:
   BEGIN OF subrc_error," Function &1 error &2 : &3 - &4
     msgid TYPE symsgid VALUE 'ZBC',
     msgno TYPE symsgno VALUE '130',
     attr1 TYPE scx_attrname VALUE 'FUNCNAME',
     attr2 TYPE scx_attrname VALUE 'SUBRC',
     attr3 TYPE scx_attrname VALUE 'PARAM',
     attr4 TYPE scx_attrname VALUE 'STEXT',
   END OF subrc_error.

 DATA: 
   funcname TYPE funct-funcname,
   subrc TYPE sysubrc,
   param TYPE funct-parameter,
   stext TYPE funct-stext.

 METHODS constructor
   IMPORTING
     !textid LIKE if_t100_message=>t100key OPTIONAL
     !previous LIKE previous OPTIONAL
     !funcname TYPE funct-funcname OPTIONAL
     !subrc TYPE sysubrc DEFAULT sy-subrc
     !param TYPE funct-parameter
     !stext TYPE funct-stext.

 CLASS-METHODS raise_if_sysubrc_not_initial
   IMPORTING
     !iv_funcname TYPE funct-funcname
   RAISING
     zcx_bc_function_subrc.

 PROTECTED SECTION.
 PRIVATE SECTION.
ENDCLASS.



CLASS zcx_bc_function_subrc IMPLEMENTATION.

 METHOD constructor.
   CALL METHOD super->constructor
     EXPORTING
       previous = previous.
   CLEAR me->textid.
   IF textid IS INITIAL.
     if_t100_message~t100key = if_t100_message=>default_textid.
   ELSE.
     if_t100_message~t100key = textid.
   ENDIF.

   me->funcname = funcname.
   me->subrc = subrc.
   me->param = param.
   me->stext = stext.
 ENDMETHOD.

 METHOD raise_if_sysubrc_not_initial.

   CHECK sy-subrc IS NOT INITIAL.

   DATA(lv_subrc_bak) = sy-subrc.

   SELECT SINGLE parameter INTO @DATA(lv_parameter)
     FROM fupararef
     WHERE funcname EQ @iv_funcname
       AND paramtype EQ @abap_true
       AND pposition EQ @lv_subrc_bak.

   SELECT SINGLE stext INTO @DATA(lv_stext)
     FROM funct
     WHERE spras EQ @sy-langu
       AND funcname EQ @iv_funcname
       AND parameter EQ @lv_parameter
       AND kind EQ @abap_true.

   IF sy-subrc NE 0.
     SELECT SINGLE stext INTO @lv_stext
       FROM funct
       WHERE funcname EQ @iv_funcname
         AND parameter EQ @lv_parameter
         AND kind EQ @abap_true.
   ENDIF.

   RAISE EXCEPTION TYPE zcx_bc_function_subrc
     EXPORTING
       funcname = iv_funcname
       param = lv_parameter
       stext = lv_stext
       subrc = lv_subrc_bak
       textid = zcx_bc_function_subrc=>subrc_error. 

 ENDMETHOD.

ENDCLASS.

Here is an example of making this exception class useful.

CLASS zcl_sample DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS sample_method RAISING zcx_bc_function_subrc.
  PRIVATE SECTION.
  PROTECTED SECTION.
ENDLCASS.

CLASS zcl_sample IMPLEMENTATION.

  METHOD sample_method.

    CALL FUNCTION 'ZFUNCTION'
      EXPORTING
        IV_PARAM1     = 'DUMMY'
      EXCEPTIONS
        some_error    = 1
        another_error = 2
        OTHERS        = 3
      ##FM_SUBRC_OK .

    zcx_bc_function_subrc=>raise_if_sysubrc_not_initial( 'ZFUNCTION' ).

  ENDMETHOD.

ENDCLASS.

The static method RAISE_IF_SYSUBRC_NOT_INITIAL will do nothing if SY-SUBRC is initial. Otherwise, it will determine the details of the function exception and raise a class based exception using that information.

Since the static method is based on SY-SUBRC, it must be placed immediately after the function call – before anything else changes SY-SUBRC.

The pragma ##FM_SUBRC_OK tells the ABAP checker that we intentionally didn’t check SY-SUBRC after the function call. We check it within the static method, but the checker wouldn’t know that.

The advantage of this method is; you don’t need to develop a custom class based exception for each function module. It would simply work with any function. The disadvantage is; it consolidates all exceptions into a single class (ZCX_BC_FUNCTION_SUBRC) so the details of the error are not easy to determine programatically. The details of the functional exception is stored as a text within the exception class and you can’t include any other variables.

Nevertheless; this is a practical approach if you don’t need all the bells & whistles and simply need to return a casual exception object in case the function returns an error.

My Books

 


Design Patterns in ABAP Objects

1464_high_res_2d

Boston, SAP Press, 2016, ISBN 978-1-4932-1465-5

Use design patterns to step up your object-oriented ABAP game, starting with MVC! Want to create objects only when needed? Call objects only when required, minimizing runtime and memory costs? Reduce errors and effort by only coding an object once? Future-proof your code with a flexible design? Design patterns are the answer! With this guide, you’ll get practical examples for every design pattern that will have you writing readable, flexible, and reusable code in no time!

– Use design patterns to write better code, faster

– Implement common architectural, structural, and behavioral design patterns

– See design patterns in action with real-world SAP applications

Link: SAP Press, Amazon

 


Ne Kadar Hayvansın

0000000444842-1

İstanbul, Pusula Yayıncılık, 2013, ISBN 605-510-602-7

Doğanın gizli programı insan ve hayvan davranışlarını nasıl şekillendiriyor?

Modern insana has üstünlük duygusunu bir an için bir kenara bırakıp doğaya; doğadaki diğer canlılara bakın. Sonra bir de kendinize bakın. İlk seferde, sosyal ortamımızın içimize kazıdığı şartlanmalarla karşılaşacaksınız muhtemelen, arada büyük farklar bulacaksınız. Bir süre sonra bir daha bakın. Bir daha… Bir daha… Önyargılarınızı bir kenara bırakıp daha dikkatli bakmaya başladıkça, aradaki farkların inandırılmış olduğunuzdan çok daha az olduğunu fark etmeye başlayacaksınız…

Erkekler neden futbola bayılır? Neden alışveriş yapmak kadınların kendini iyi hissetmesini sağlar? Seksten sonra neden erkekler uyumak isterken kadınlar canlanmış olur? Korku filminden sonra yorgana sarılınca neden kendimizi güvende hissederiz?

Doğadaki bütün canlılar, ortak bir programla dünyaya gelir. Bu program, insanda da vardır, köpekte de; ayıda da vardır, kaplanda da. Bu programı anlayabilen biri, kendine ve başka insanlara ait davranışların çok büyük bir kısmını da anlayabilir, açıklayabilir, hatta öngörebilir.

Dr. Kerem Köseoğlu, söz konusu programı deşifre edip herkesin anlayabileceği bir şekilde açıklıyor. Kitabı okudukça ve kendi içinizdeki programı da gözlemlemeye başladıkça; aslında her şeyin ne kadar basit olduğunu göreceksiniz. Hatta bu kadar uzun zamandır bu kadar açık bir şekilde ortada olan bir şeyi, nasıl olup da keşfedememiş olduğunuza şaşıracaksınız belki de…

Kolay okunan, pek çok konudaki görüşlerinizi değiştirecek ve size yeni bir bakış açısı kazandıracak, keyifli bir kitap… En önemlisi, diğer canlılara ve kendinize daha anlayışlı ve daha hoşgörülü davranmanızı sağlayacak!

Link: Pusula, Amazon, D&R, HepsiBuradaIdefix, KitapYurdu

 


Veritabanı Mantığı (10.)

0000000185275-1

İstanbul, Pusula Yayıncılık, 2005, ISBN 975-647-756-3

Bu kitapta yazar, SQL’in ne olduğu ve nasıl kullanıldığı gibi konulardan önce, veritabanı kavramına değiniyor. Bu çerçevede; veritabanının ne olduğu, nerelerde hangi amaçlarla kullanıldığı, nasıl hazırlanıp programlandığı gibi konulara açıklık getiriyor. Özellikle; yeni oluşturulan bir veritabanı içerisinde tablo tasarımının nasıl yapılması gerektiği konusu üzerinde ayrıntılı bir biçimde duruluyor. Yaygın olarak kullanılan tüm veritabanı programlarının ortak dili olan SQL’i öğretmek amacıyla hazırlanan bu kitapta, her konu birden çok örnekle anlatılıyor ve birkaç kez MS-Access programını çalıştırmış bir kullanıcının bile rahatça takip edebileceği bir dil kullanıyor.

Link: Pusula, Amazon, D&R, HepsiBuradaIdefix, KitapYurduDownloads

 


Bilgisayar Destekli Müzik

0000000180374-1

İstanbul, Pusula Yayıncılık, 2005, ISBN 975-6477-53-9

Bilgisayar desteği arkanızda olduğu sürece, evinizde ekonomik yollardan müzik yapabilirsiniz! Fazla masraf yapmadan kendi ev stüdyonuzu kurabilir ve odanızda yaptığınız çalışmalarla profesyonel kayıt stüdyolarını aratmayacak sonuçlara imza atabilirsiniz.

Kitapta bahsedilen programları kullanarak ruhunuzdan dökülen notaları dijital ortama aktarabilir, üzerlerinde sayısız düzenleme yapabilirsiniz. Tüm bunları; ortalama bir bilgisayar, doğru seçilmiş bir ses kartı ve program ile kolayca gerçekleştirebilirsiniz!

• MIDI nedir?
• Audio Nedir?
• Popüler Müzik Programları: Sequencer, Loop, Audio Düzenleme, Notasyon, SoundFont Programları
• Adım adım örnek uygulamalar
• Cakewalk Sonar ve Sound Forge Programlarının detaylı anlatımı
• Loop bazlı projeler ve Fruity Loops
• Notasyon ve Sibelius

Kendi müziklerinizi nasıl hazırlayacağınızı adım adım tarif eden kitapla birlikte, yazarın Audio çalışmalarını ve kitapta kullanılan programların deneme sürümlerini içeren CD de hediye!…

 


Programcılık Mantığı (9.)

0000000160095-1

İstanbul, Pusula Yayıncılık, 2004, ISBN 975-647-738-5

Programcılık nedir? Programcı olabilmek için neler gerekir? Kimler programcı olabilir? Programcılar ne yapar? Programcı kimdir?

• Programlama dilleri ve karşılaştırmaları
• Programcılık Terimleri
• Temel Algoritma Öğeleri
• Mantıksal Operatörler
• Akış Şemaları
• Nesne Temelli Programlama
• Görsel Programcılık

Bu sorulardan yola çıkarak, programcılığı masaya yatıran Programcılık Mantığı, programcı olmak isteyen ama nereden başlayacağını bilemeyenler için yazılmış benzersiz bir kaynak. Temel programlama öğelerinden, görsel programcılığa, programcılık terimlerinden nesne temelli programlamaya kadar, programcılık hakkında bilmek isteyeceğiniz her şey bu kitapta yalın bir dille ve günlük hayattan örneklerle anlatılıyor. Programcılığa nereden başlayacağını bilemeyenler, bu kitap tam sizin için. Değişkenler, fonksiyonlar, sınıf ve nesneler, akış şemaları, görsel programcılık, nesne temelli programlama gibi temel programlama konularını detaylı olarak inceleyen kitap, işlediği her konu için Java, C#, VB.NET ve Delphi’de yazılmış örnek uygulamalar da içeriyor. Böylece en çok kullanılan bu dört programlama dilini de bir arada görme ve kıyaslama imkânı da sunuyor.

Algoritma yapılarını, günlük hayattan örneklerden yola çıkarak anlatan, her uygulamanın dört ayrı dilde yazımını veren bu kitap, bu özellikleriyle Türkiye’de bir ilk.

Link: Pusula, Amazon, D&R, HepsiBurada, Idefix, KitapYurdu, Downloads


Bir Romeo Bir Juliet

screen-shot-2016-10-24-at-18-19-22

İstanbul, Self, 1999

 

Romeo geceye bakıp Juliet’i her düşündüğünde
Bir yıldız kayar Juliet’in gözlerine ve biraz daha parlar gece…
Juliet geceye bakıp Romeo’yu her düşündüğünde
Bir yıldız daha kayar Romeo’nun içine ve derinliklerde kaybolur gider… Aslında bilirler ki Romeo ile Juliet,
Güneş onların birbirlerini bulduğu gün bir daha doğmayacak…
İlkin son ve sonun ilk olacağı ilk ve son karşılaşma olacak bu…
Romeo ilk ve son kez Romeo,
Juliet ise ilk ve son kez Juliet olacak…

 

ABAP Group Operations in Internal Tables

1464-ppt

Today, we will be inspecting some cool grouping techniques introduced in ABAP 7.40.

First, let’s get familiar with our context. We will read the table T001K, where BWKEY (valuation area) is the table key, but BUKRS (company code) is repeated multiple times in various lines. Let’s start off by reading this table.

SELECT * INTO TABLE @DATA(gt_t001k) FROM t001k ORDER BY bukrs.

So far so good. Now, our goal is to build a list of unique BUKRS values. Using classical ABAP, this is possible via the COLLECT command.

TYPES:
  BEGIN OF t_bukrs,
    bukrs TYPE bukrs,
  END OF t_bukrs,

  tt_bukrs TYPE STANDARD TABLE OF t_bukrs WITH DEFAULT KEY.

DATA:
  gs_bukrs TYPE t_bukrs,
  gt_bukrs TYPE tt_bukrs.

LOOP AT gt_t001k ASSIGNING FIELD-SYMBOL().
  gs_bukrs-bukrs = -bukrs.
  COLLECT gs_bukrs INTO gt_bukrs.
ENDLOOP.

If we move forward to ABAP 7.40, we can achieve the same result with a better approach:

DATA(gt_bukrs) = CORRESPONDING tt_bukrs( gt_t001k ).
SORT gt_bukrs BY bukrs.
DELETE ADJACENT DUPLICATES FROM gt_bukrs COMPARING bukrs.

However, we can reduce the code even more by using the group command.

DATA(gt_bukrs) = VALUE tt_bukrs(
  FOR GROUPS gr1 OF gs_t001k
  IN gt_t001k
  GROUP BY gs_t001k-bukrs (
    bukrs = gr1
) ).

Cool eh? Just one line of code, and you are there!

Things get cooler when you want to do operations by grouping the data in an internal table. For example; you want to write the BWKEY’s corresponding to each BUKRS. Without grouping, you would first build GT_BUKRS, and then write two nested LOOPs to achieve that.

LOOP AT gt_bukrs ASSIGNING FIELD-SYMBOL().

  NEW-LINE.
  WRITE AT 1(5) 'Group'.
  WRITE AT 7(20) -bukrs.

  LOOP AT gt_t001k
    ASSIGNING FIELD-SYMBOL()
    WHERE bukrs EQ -bukrs.

    NEW-LINE.
    WRITE -bwkey.

  ENDLOOP.

ENDLOOP.

However; using the grouping option, you don’t even need to build GT_BUKRS. You can achieve the same goal by using GT_T001K alone.

LOOP AT gt_t001k
  INTO DATA(gs_line)
  GROUP BY ( gr_bukrs = gs_line-bukrs )
  ASCENDING
  ASSIGNING FIELD-SYMBOL().

  NEW-LINE.
  WRITE AT 1(5) 'Group'.
  WRITE AT 7(20) -gr_bukrs.

  LOOP AT GROUP  ASSIGNING FIELD-SYMBOL().
    NEW-LINE.
    WRITE: -bwkey.
  ENDLOOP.

ENDLOOP.

And voila! This technique can be used for multi level grouping as well. Check the following code sample:

SELECT
    ekko~ebeln,
    ekpo~ebelp, ekpo~matnr,
    eket~etenr, eket~eindt, eket~menge
  INTO TABLE @DATA(gt_all)
  FROM
    ekko
    INNER JOIN ekpo ON ekpo~ebeln EQ ekko~ebeln
    INNER JOIN eket ON
      eket~ebeln EQ ekko~ebeln AND
      eket~ebelp EQ ekpo~ebelp
  WHERE
    ekko~ebeln EQ '5500000026' OR
    ekko~ebeln EQ '5500000027'.

LOOP AT gt_all
  INTO DATA(gs_1)
  GROUP BY ( ebeln = gs_1-ebeln
             ebelp = gs_1-ebelp
           )
  ASCENDING
  ASSIGNING FIELD-SYMBOL().

  NEW-LINE.
  WRITE:
    'Outer loop for ',
    -ebeln,
    -ebelp.

  LOOP AT GROUP 
    INTO DATA(gs_2)
    GROUP BY ( ebeln = -ebeln )
    ASCENDING
    ASSIGNING FIELD-SYMBOL().

    NEW-LINE.
    WRITE:
      'Inner loop for ',
      -ebeln.

  ENDLOOP.
ENDLOOP.

GROUP command has many further applications in internal table operations, which I might write in more detail someday. You can check Google or ABAP help for further use.

Dirty Assignment of Local Variables in ABAP

1464-ppt

Dirty assignment is a technique we all use sometimes. Imagine that the ABAP program ZPROG1 makes a call to ZCLASS=>METHOD1. If METHOD1 needs to access a global variable within ZPROG1, the following trick can be used:

ASSIGN ‘(ZPROG1)GV_SAMPLE’ TO .

 = 5.

This code will change the value of the global variable GV_SAMPLE within ZPROG1. Although this operation is highly insecure and may cause instabilities, it is a dire technique needed at times.

So far so good. It works fine on global variables. But what about local variables? What if your method needs to access a local variable; in a form, for instance? Check the following case:

REPORT zprog1. 

FORM form1.

  DATA lv_local TYPE i.

  lv_local = 5.

  ZCLASS=>METHOD1( ). 

ENDFORM.

Imagine that you need to access lv_local from within METHOD1. Assigning ‘(ZPROG1)LV_LOCAL’ doesn’t work because lv_local is not a global variable.

Well, here is the trick. Create an enhancement in FORM1 where you send the data reference of LV_LOCAL to ZCLASS.

REPORT zprog1.

FORM form1.

“””””””””” ENHANCEMENT

  FIELD-SYMBOLS  TYPE i.

  ASSIGN (‘lv_local’) TO .
 
  ZCLASS=>SET_REF_OF_LV_LOCAL( iv_local_ref = REF#(  ) ).

“”””””””””

  DATA lv_local TYPE i.

  lv_local = 5.

  ZCLASS=>METHOD1( ).

ENDFORM.

Please note that you can’t assign LV_LOCAL directly because at the point of enhancement, it is not defined yet. But you can assign it dynamically as (‘LV_LOCAL’).

The imaginary method ZCLASS=>SET_REF_OF_LV_LOCAL will store the reference somewhere within the class:

METHOD set_ref_of_lv_local.

  gr_local = iv_local_ref.

ENDMETHOD.

At this point, ZCLASS=>METHOD1 can access the local variable easily.

METHOD method1.

  FIELD-SYMBOLS  TYPE i.

  ASSIGN gr_local->* TO .

  ADD 1 TO .

ENDMETHOD.

Neat, eh?