Skip to Content
Event Information

Annotated links: Episode 47 of Hands-on SAP dev with qmacro

This is a searchable description of the content of a live stream recording, specifically “Ep.47 – ABAP and SAP Cloud Platform functions for Advent of Code” in the “Hands-on SAP dev with qmacro” series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the “Catch the replays” section of the series blog post.

This episode was streamed live on Fri 06 Dec 2019 and is approximately 60 minutes in length. The stream recording is available on YouTube.

Brief synopsis: It’s December and many of us are furiously hacking away on solutions to the excellent Advent of Code daily puzzles. We’re using different languages, platforms and tools, for different reasons; in this episode we get Hendrik Neumann and Gregor Wolf to show us how they’re solving the puzzles with SAP tech.

00:03:15 Setting the scene, showing Advent of Code – a series of daily programming puzzles that many folks, a vast number of folks around the world, are using to have some fun, learn a new language or a new programming technique, and generally improve their skills.

00:04:25 Also, introduced to us by Gregor Wolf, there’s 25 Days of Serverless which follows a similar pattern of daily programming challenges, this time to be solved in a serverless context.

00:04:55 A quick reminder that the SAP Cloud Platform has a beta Functions-as-a-Service (FaaS) offering, for which I’ve created a second subaccount in my trial account, in order to be able to turn on “beta features” to access this offering.

00:05:50 Hendrik Neumann is going to show us some of his coding for Advent of Code solutions that he wrote in ABAP, and that reminded me to share the link to the SAP TechEd App Space missions from this year, which includes one for the SAP Cloud Platform ABAP Environment.

00:06:50 Moving to the main scene to bring in Hendrik and Gregor who have been waiting patiently in the Green Room (!). We had some issues with Hendrik’s audio initially, so we started with Gregor.

00:10:20 We get going with Gregor showing us a solution to the first challenge relating to generating a service that effectively “rolls the dice” for a dreidel with four different values.

00:11:25 We talk about continous trial renewal (on SAP Cloud Platform Cloud Foundry), and that after 90 days all artifacts are deleted, but can be re-created afterwards. Gregor (and I, and others, I’m sure) uses GitHub to store artifacts to be able to more easily re-create them in this way.

00:11:45 Gregor started off with the SAP Web IDE using the project wizard to get a template for creating a FaaS application. The resulting simple application is effectively a single handler function that is exported, and simply responds to an incoming event (an HTTP request, in this case).

00:13:10 Just before deploying this simple function to the SAP Cloud Platform, Gregor points out a gotcha that you need to pay attention to, otherwise things won’t work generally. This is documented in the help document Create a Functions (Beta) Service Instance and basically involves manually specifying the service instance name in a small JSON stanza like this:

{
  "name": "faas-test"
}

00:14:20 After deployment, we test it out, via a FaaS cockpit page relating to Gregor’s FaaS subscription. The URL of this cockpit page will look something like this:

https://<your-id>beta.cockpit.<region>.functions.ondemand.com/#/overview

It’s a nice overview with access to the functions, triggers, and so on. Taking the HTTP endpoint that represents the trigger for the FaaS handler, Gregor calls the service.

00:16:30 Moving on to the challenge in Day 3, Gregor takes us through what was involved, including GitHub Webhooks. This time Gregor shows that he moved to a local development context for this one, using the Functions (Beta) Library, described in the SAP Help document Create a Function Project with Functions (Beta) Library. Nice find, Gregor!

00:18:10 We see that after creating the project, he transferred it via a git repo to his local environment, using VS Code as the IDE, and adding a few scripts to the project’s package.json. Running npm run watch spins up a local server with endpoints representing the functions. Lovely!

00:20:00 Gregor shows us the content of his githubwebhook.js code, and we take a short digression on coding and putting things together. There’s no shame in what your code looks like, and if it works and is maintainable, so much the better! We notice that Gregor is using the built-in http module to make the HTTP requests – this is because he didn’t want to rely upon any further external packages here.

00:22:30 There’s another component to this Day 3 puzzle solution, which is a backend, which Gregor has put together using of course CAP. He has a really simple data model which looks like this:

namespace media;

entity Pictures {
  key ID : String(64);
  @Core.MediaType: 'image/png'
  content : LargeBinary;
}

along with an even simpler service definition:

using media as db from '../db/data-model';

service MediaService {
  entity Pictures as projection on db.Pictures;
}

00:24:40 Looking briefly at the REST Client extension for VS Code which allows you to write HTTP client request definitions really simply. Recommended!

00:27:00 After inserting a picture, Gregor demonstrates the deletion facility. He also shows the test he set up to simulate what is sent from GitHub in the webhook call – this was fairly straightforward to set up as GitHub documents that very nicely.

00:29:25 Making the ‘real’ test – taking a screenshot, committing it into the git repo and pushing the change to GitHub, whereupon the webhook call is triggered. And we see both from the GitHub webhook status page, and from requesting a list of images from the CAP-powered backend, that everything was successful. Well done Gregor, and thank you!

00:33:35 Bringing in Hendrik now, who is happily free of audio issues too by now. He’s been solving Advent of Code puzzles, in a test driven development (TDD) approach, in ABAP, on a privately installed virtual machine running a developer edition ABAP stack on his laptop.

00:35:45 He fires up Eclipse, and we see the (by now) familiar sight of the ABAP Development Tools (ADT) in action there. He’s solved the puzzles for Days 1 through 4. He points out, rightly, that with the innovations that have been arriving since 7.4, the ABAP language is great and far from ‘dead’!

00:36:40 Hendrik starts by showing the Day 1 puzzle, which involves some calculations of fuel. He also shows how the second part of the day’s puzzle appears once a correct answer for the first part has been submitted.

00:38:00 He shows us the ABAP code for calculating the fuel in all its glory. It’s a wonder to see, and rather beautiful in its own way. Here’s what the implementation section looks like:

CLASS zfuel IMPLEMENTATION.

  METHOD calc.
    DATA(x) = CONV i( floor( CONV float( mass / 3 ) ) ) - 2.
    fuel = COND #( WHEN x < 0 THEN 0 ELSE x + calc( x ) ).
  ENDMETHOD.

  METHOD calc_total_fuel.
    total_fuel = REDUCE #( INIT x = 0 FOR module in modules
                           NEXT x = x + calc( module ) ).
  ENDMETHOD.

ENDCLASS.

I have typed this in here so we can all stare at it for a few minutes. Go over to the video to watch Hendrik’s explanation, but before you do, notice here that you’re looking at recursion (in the calc method) and also a reduce call (even though it looks a little unusual, to say the least!). Wonderful.

00:40:30 Hendrik takes us briefly through his local test class too, containing tests taken from the examples in the puzzle.

00:41:00 To get the solution output, Hendrik has created a small program that uses CL_GUI_FRONTEND_SERVICES to facilitate the upload of the input data file, and to call the solution functions in the context of a call to the static DISPLAY method of CL_DEMO_OUTPUT, which allows him to see the output directly in Eclipse.

Here’s the line, so we can stare at that, in all its glory, too:

cl_demo_output=>display( |Total fuel: { NEW zfuel( )->calc_total_fuel(
  VALUE #( FOR module IN modules ( CONV #( module ) ) ) )  }| ).

And Hendrik even wrote the tests first, a proper TDD approach. Good work Hendrik!

00:43:25 We move over to Day 3 and talk about the challenges presented by that day’s puzzle. In the chat, Helmut Tammen notes that this puzzle caused difficulties for him in the solution – he has been using Lodash FP and it turned out that the built-in intersection function was basically too slow. The odd thing is that the same thing happened to me, while using Ramda, a similar FP library for JavaScript. Furthermore, my son Joseph had the same issue. We all ended up writing our own implementations of intersection. How’s that for interesting?

In case you’re wondering, here’s what my implementation of a faster intersection looks like:

const fasterIntersection = (list1, list2) => {
  const serialise = JSON.stringify
  const deserialise = JSON.parse
  const [shorter, longer] = lift(map(serialise))(list1 < list2 ? [list1, list2] : [list2, list1])
  return map(deserialise)(reduce((a, x) => concat(a, gte(indexOf(x, longer), 0) ? [x] : []), [], shorter))
}

00:46:40 After a comment in the chat, we go back to examine the COND conditional operator, which reminds me of the ternary operator in other languages. Hendrik explains a little bit more about this expression, in particular the type inference from fuel and what it must construct from the expression evaluation. These are referred to as “constructor expressions”.

00:50:00 We take a brief philosophical view of how the reduce concept has been realised in ABAP, which is different from most of the implementations one sees in the wild in other languages which are more closely aligned with functional approaches.

Note that Hendrik has shared his ABAP solutions to these Advent of Code puzzles in a GitHub repo: https://github.com/hendrik77/Advent_of_Code_2019, thanks to abapGit, which in turn is thanks to Lars Hvam who is live with us in this live stream episode too – excellent (and thanks Lars)! Hendrik gives a further shout out to Enno Wulf who is also sharing his ABAP based solutions to Advent of Code here: https://github.com/tricktresor/AdventOfCode2019, and to Nabheet Madan who wrote a blog post on the subject: Advent of code – Let’s do it using ABAP.

00:56:10 Just before we finish this episode, Hendrik points us to some regular expressions he’s used to implement part of the solution to Day 4. This reminds me to mention an excellent book from which I learned a lot about regular expressions – Jeffrey Friedl’s Mastering Regular Expressions – definitely recommended!

And we finish on a quote, from Jamie Zawinski: Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems..

Until next time, happy hacking!

Be the first to leave a comment
You must be Logged on to comment or reply to a post.