Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
alexd
Advisor
Advisor


For those stepping into the world of ERP and SAP for the first time, the plethora of terms and concepts can feel overwhelming.

If you are a software savvy individual who has no prior or limited knowledge of SAP ERP and terms like ABAP,Z Transactions, BADI or se38 means nothing to you this blog series is for you.

All you need to bring, is a basic understanding of programming in Python and a curiosity to explore enterprise technologies.

We will start with this blog tackling the keep the core clean concept. There are numerous blogs explaining thoroughly what it is and why it is critical when architecting the ERP landscapes of the future.
However, as an abstract concept, it must hold a significant position on your priority list whenever you're crafting practically any piece of software and that would be to design modular systems.

 

Let’s explain that using solely basic Python along with business logic from our everyday experiences.

Lead time is a vital KPI within an ERP system, but for now, we're setting aside our SAP perspective.

Think of lead time as the time it takes for an online store to deliver the fruits you have ordered right to your door, starting from the moment you place the order. Sometimes, this duration might extend to 40 minutes, other times to 37, and occasionally even just 29.

So, my friend Mike asks one day..."Alex how long does it take on average to get your fruits from the online store?"

And... instead of taking 5 seconds to perform the calculation, I create a dedicated function in Python. Maybe there is a hidden business opportunity here!

 
#initial function
def calculate_average_lead_time(lead_times):
total_lead_time = sum(lead_times)
num_cases = len(lead_times)

average_lead_time = total_lead_time / num_cases
return average_lead_time

lead_times = [40, 37, 29, 31, 38, 100]
average_lead_time = calculate_average_lead_time(lead_times)
print(f"Average Lead time: {average_lead_time:.2f} minutes")
--
Average Lead time: 45.83 minutes

 

News has spread regarding this function, and two of Mike’s friends have expressed interest in utilising it for their own calculations, based on their specific lead times.

As I am not currently positioned to provide a cloud-based solution, I distribute copies of the source code to all those who have asked for it.

Let’s call these new friends (aka. customers) Mister Brown and Miss Green.

So, I am packaging the function in a bundle, and I am releasing version 1.0. Hurray!

These customers have paid a significant amount of money for the function, and they have also acquired a maintenance plan to address any potential bugs in the future.

 

Two months later.

Miss Green is very happy with the function. No problems or features requested so far. Only some minor bugs reported which have been planned for next release.

On the other hand, even though Mr. Brown was initially happy with the function, there's now a need to add some extra business logic.
Mister Brown: I want to calculate the average lead time only for cases where the lead time is below a certain threshold.

 

Hold on a minute.

Does this calculation fall under the scope of my standard function? No.

Do I, the function provider, have the capability to modify this function?

Yes, but let's pause for a moment before doing so.

This requirement is highly specific to Mister Brown. What if nobody else requires that feature?

Moreover, I'm uncertain about the timing of my next release and Mister Brown requires this calculation to be in production urgently!

 

No problem.

My function’s distributions come with the source code so Mister Brown takes full advantage of that flexibility I provide and customises the initial function adding his extra piece of logic required. And that concept can apply for all the Mister Browns of the world who have their own unique business requirements. No problem.
#mr brown
def calculate_average_lead_time(lead_times, threshold):

filtered_lead_times = [time for time in lead_times if time <= threshold]

total_lead_time = sum(filtered_lead_times)
num_cases = len(filtered_lead_times)
average_lead_time = total_lead_time / num_cases
return average_lead_time

lead_times = [40, 37, 29, 31, 38, 100]
threshold = 35

average_lead_time_fast = calculate_average_lead_time(lead_times, threshold)
print(f"Average Lead Time: {average_lead_time_fast:.2f} minutes")
--
Average Lead Time (Fast Cases): 30.00 minutes

 

6 months later. Problem.

Upon conducting a thorough code review of the function, I have pinpointed a deficiency in terms of defensive checks, which is necessary to prevent runtime errors.

One crucial measure is to include protection against division by zero, especially in the unlikely scenario where either a system or a user supplies an empty array of lead times.
if not lead_times:
return 0

The time for release 1.1 is here and the function now looks like below:
#with fix
def calculate_average_lead_time(lead_times):

if not lead_times:
return 0

total_lead_time = sum(lead_times)
num_cases = len(lead_times)

average_lead_time = total_lead_time / num_cases
return average_lead_time

 

Hence, my clients are ready to embrace this fresh release along with its latest fix.

Nevertheless, Mr. Brown has made modifications to the original function.Consequently, we now have two distinct versions of the same function, each incorporating additional elements of functionality.

Options to move forward.

  1. Mr. Brown to copy and paste (or merge, for the Git enthusiasts) the delta between the two functions to create one copy. Certainly, why not, it is just two lines of code. However, this blog is a fictional representation of a highly intricate scenario. This course of action is not viable in real life.

  2. Brown could skip the latest release. (Surprise: We can safely assume that Mr. Brown will skip ALL next releases of this function.)


What I could have done to avoid this situation:

I could have made it easier for my customers to extend the function without having to alter the initial one.

There are many ways to design that, but one very straightforward way would be to provide some enhancement points in predefined locations in my standard function code where customers could add their custom code.

Here how it may look like:
def calculate_average_lead_time(lead_times):
#The Fix
if not lead_times:
return 0

#This function will stay here FOREVER.
extend_functionality(lead_times)

total_lead_time = sum(lead_times)
num_cases = len(lead_times)

average_lead_time = total_lead_time / num_cases
return average_lead_time

#Custom code goes only here
def extend_functionality(lead_times):
threshold = 35
lead_times[:] = [time for time in lead_times if time <= threshold]

I am providing a method called extend_functionality where everyone could add their custom code without altering the core function (aka. keep the CORE clean). As such, the (naive) fix check if lead_times is empty, could be included quite easily.

Outro


Now, let's examine how the terminology we employed in the narrative aligns with the realm of ERP systems:

  • Within our narrative, the function we developed serves as an analogy for an ERP system.

  • Much like the lead time function encapsulates the core logic, an ERP system encompasses all crucial processes, logic, and data that drive a business.

  • In a broader context, Mr. Brown represents every customer who has distinct needs and business prerequisites (as this mirrors reality).

  • I'll leave it to you to draw parallels between the extend_functionality concept and an SAP ERP system. Feel free to share your insights in the comments below if you wish.

  • Spend some to contemplate what it means for Mr. Brown if he could not update the core function with any bug fixes OR Innovations (more on this on next blog)


 

By now, you might have thought that extending an ERP only involves making changes within the ERP itself, but that's not (entirely) true.

So in the next blog, I'll explain how this idea connects with SAP Business Technology Platform (BTP).

Stay tuned for more content on becoming an S/4HANA extension expert.