Posted in 2024
What is a Research Software Engineer?
- 2024 Nov 20
What is a Research Software Engineer (RSE)? Too many things to define, you can find these definitions elsewhere. Maybe the question you would like to know is How do I get value from Research Engineers like Aalto Scientific Computing does? - that’s what we’ll try to answer here. Through that, we may learn a functional definition.
This page is written from the perspective of computational science - similar messages may apply to other fields. Note that computing and AI is in every field now.
When someone wants Research Engineers, it’s probably because they see something that is missing in the current academic system. Thus, to understand what we want, we need to understand the system. Below is rkdarst’s current mental model:
Academics are who we usually consider researchers. They do research, and are promoted based on articles published and citations received from other academics. Citations from academics tend to focus on innovation and novelness, so that’s what decides career paths.
Research Engineers (REs) focus on the practice and “structural integrity” of the research: the tools, the reproducibility, and more. They are more concerned with the work being done well, than pure novelness and citations. [0]
Research Software Engineers (RSEs) are a subset of Research Engineers, and I feel that the “software” is the least significant part there. Software is important, but so is data, computing, reproducibility, etc.
Particular examples of things that Research Engineers are good at include: Reproduciblity, maintaining software and data across academic generations, Open Science, programming, using large computer clusters, data security, and research ethics processes.
Researchers, in my mind, cover both of the above (and more). Industrial research teams would have both of the above and possibly even more different roles all working together on their problems. In universities, we tend to only consider the academics to researchers.
So what’s a Research Engineer? To me, it’s defined mostly in terms of what is missing from the typical academic career path (of undergraduate → junior researcher → senior researcher). At all levels, I’ve seen research engineering under-valued and under-taught (not necessarily because it’s not wanted, but because it’s not novel science and there’s no time). Senior researchers (group leaders) often see the value, but don’t have the time (or sometimes ability) to train and supervise research engineers well.
Years before Aalto RSE started (~2017-2018), I saw a need for more basic skills (for example: version control to manage code) and worked to promote them in undergraduate programs. This basically didn’t work, because they were seen as not scientific thus not something to be taught in academic courses (and if they were thought, the courses would be full of people looking for easy ECTS). While there certainly are study programs in software and software engineering, these are their own thing, and not part of data science, or other fields that need computation. Software engineering programs also aren’t adapted for the unpredictibility of research.
This was the prompting to start Aalto Research Software Engineers - if we can’t teach people skills in study programs, we have to support them when they become researchers (and teach it via practical mentoring). This has worked out very well, as you can see by our rapid expansion and heavy usage.
Aalto RSE is essentially the collaborator our research groups need to do their top-level work. This system works very well, but are there other options?
The above leads to various ideas. Take your pick for what angle you want to approach the problem:
Better RE teaching in undergraduate programs:
As part of existing programs (is there time to teach this? Is there desire? On the other hand, RE skills are great for employment prospects)
As dedicated majors? (Some people are trying to make dedicated RSE study programs at different universities, and there is a value there. But if you ask me the best value is learning RE along with academic research in a different field)
Better RE teaching in graduate programs:
Many of the same things as above apply here, mainly the lack of time, and the necessity to spend time on novel research, not learning existing best practices.
Nurture REs within existing research groups:
Nothing stops group leaders from hiring students and postdocs who have chosen to focus on research engineering. This often happens when supervisors hire technical postdocs to manage the RE side of things. (The question is: can they be supervised and mentored well by academic supervisors, if they need to be home-grown?)
If group leaders hire good candidates, Aalto RSE can help mentor them. See the companion blog post RSE work rotations for one idea.
Recruit REs as professor-level group leaders” similar to how senior academics are recruited:
These people would focus on collaborating with others to make projects possible.
The university systems don’t seem set up to value these people, thus they don’t appear among the ranks. They could appear if they spent their careers chasing academic citations, but then would they be able to spend enough time on research engineering?
I think this is what some people mean when they say they want a RSE career path: a way to recruit senior academics who lead research engineering groups. I think the idea is good but it’s not how universities are set up, so it’s a long way off. The values systems may not even match up.
Create parallel structures that support research engineering
That is what Aalto RSE has done. We are researchers, but we make new research possible by collaborating with academics, instead of trying to publish by ourselves. We are part of the services of the School of Science.
We also take it upon ourselves to do teaching and mentoring via co-working for all types of researchers (aspiring academic or research engineer). We can fill in the technical mentoring that’s missing by many supervisors.
You can read about our history in more detail.
I’ve seen many people interested in gaining research engineering competence for their organization. You need to develop an environment where they fill in the gaps you need.
Junior academics: encourage them to explore their technical skills. Show that there is value in this, even if it reduces the number of publications. Encourage them to get training (for example the Aalto RSE training). Give them time, encouragement, and career prospects to reach beyond the focus on papers.
Other support staff at universities and other organizations: don’t view them as limited-purpose supporters of an {infrastructure, service, process}. View them as supporters of research: let them holistically support research projects from many angles at once, rather than only in narrow silos with strict project reporting requirements.
You can hire dedicated staff to be REs, but it’s important that they are integrated into the local research environment. Most of our hires have been local staff who have grown into a new role, and I think this is how it should be.
Any of the above, especially the first two, require time being made available for RE work and a clear vision and network. Aalto RSE (with the help of others in Finland) is planning on making a networking and onboarding program for new research engineers who wish to adopt this vision.
If you read this far, you probably see the value in research engineers and want them yourself. Just hiring someone, or changing someone’s job to “RSE”, won’t magically solve the problem you need. It’s a whole mindset shift towards a multi-disciplinary research team.
What’s the right level of research engineers, permanent and experienced or junior and learning? Probably a bit of both.
I know that “Research Engineer” is a job title that can have other definitions.
How busy is the cluster? A discussion
- 2024 Oct 21
We occasionally get some questions: how busy is the cluster? How long do I have to wait? Is there some dashboard that can tell me?
The answer is, unfortunately, not so easy. Our cluster uses dynamic scheduling with a fairshare algorithm. All users have a fairshare priority, which decreases the more you have recently run. Jobs are ranked by priority (including fairshare plus other factors), and scheduled in that order. If there are unschedulable holes between those jobs, it can take a job with a lower priority and fill them in (“backfilling”). So that gives us:
A small-enough job with a low priority might still be scheduled soon.
A higher priority user could submit something while you are waiting, and increase your wait time.
An existing job could end early, making other wait times shorter.
An existing job could end early, allowing some other higher priority jobs to run sooner, making backfilled jobs run later.
In short: there is no way to give an estimate of the wait time, in the way people want. We’ve tried but haven’t find a way to answer the question well.
What can we know?
You can compare your fairshare factor with other users. If you run
sshare you can see the fairshare (higher means higher priority).
sprio shows relatively priority for all jobs (here, the raw values
are multiplied by some factor and added). On Triton (the new install
since 2024 may), they mean the following:
at 7 days) (zero when first submitted, increasing to 10000 at 7 days old)
The fairshare factor is “1e7 × FairShare priority from sshare”
The FairShare value is computed based on the raw usage value: at each level of the share tree, it divides it up among the users so that those who have run less have a higher priority.
The usage value decays with a two-week half life.
The others are mostly constant.
Still: this is all very abstract and what others submit has more effect than your priority. The only thing you can control is using less resources.
This is quite cluster dependent so we’d recommend asking for help for how your own cluster is setup.
This may be your real question. There are two main things:
Use less resources. Make sure you don’t over-request more than you need (CPU, memory, GPUs) - this will affect your future fairshare less. Of course, use everything you need, “saving for later” doesn’t give you more resources than you save now.
Request less resources per job. This will let you be backfilled into the scheduling holes (see below).
In this case, if there is a slot for you, you are scheduled very soon.
srun --test [RESOURCE_REQUESTS] might give you some hint about
when a job would be scheduled - it basically tries to schedule an
empty job and reports the currently estimated start time. (It uses a
JobID though so don’t run it in a loop)
In this case, nothing can be said since the queue is always being re-shuffled. In the long-run, you get a fair share of resources. If you haven’t used much lately, you have more now. Your wait time depends more on what other users submit (and their priorities) than what you submit - and this is always changing. You can tell something about how soon you’d be scheduled by looking at your priority relative to other users. Make your jobs as small and efficient as possible to fit in between the holes of other jobs and get scheduled as soon as possible. If you can break one big job into smaller pieces (less time, less CPU, less memory) that depend on each other, then you can better fit in between all of the big jobs. See the Tetris metaphor here in TTT4HPC
If your need is “run stuff quickly for testing”, make sure the jobs are as short as possible. Hopefully, your cluster staff about development or debugging partitions that may be of use, because that’s the solution for quick tests.
This description was in an old version of our docs but has since been removed. The exact values are out of date. It’s included here for detailed reference anyway:
Triton queues are not first-in first-out, but “fairshare”. This means that every person has a priority. The more you run the lower your user priority. As time passes, your user priority increases again. The longer a job waits in the queue, the higher its job priority goes. So, in the long run (if everyone is submitting an never-ending stream of jobs), everyone will get exactly their share.
Once there are priorities, then: jobs are scheduled in order of priority, then any gaps are backfilled with any smaller jobs that can fit in. So small jobs usually get scheduled fast regardless.
Warning: from this point on, we get more and more technical, if you really want to know the details. Summary at the end.
What’s a share? Currently shares are based on department and their
respective funding of Triton (sshare). It used to be that
departments had a share, and then each member had a share of that
department. But for complex reasons we have changed it so that it’s
flat: so that each person has a share, and the shares of everyone in a
department corresponds to that department’s share. When you are below
your share (relative to everyone else), you have higher priority, and
vice versa.
Your priority goes down via the “job billing”: roughly time×power. CPUs are billed at 1/s (but older, less powerful CPUs cost less!). Memory costs .2/GB/s. But: you only get billed for the max of memory or CPU. So if you use one CPU and all the memory (so that no one else can run on it), you get billed for all memory but no CPU. Same for all CPUs and little memory. This encourages balanced use. (this also applies to GPUs).
GPUs also have a billing weight, currently tens of times higher than a
CPU billing weight for the newest GPUs. (In general all of these can
change, for the latest info see search BillingWeights in
/etc/slurm/slurm.conf).
If you submit a long job but it ends early, you are only billed for the actual time you use (but the longer job might take longer to start at the beginning). Memory is always billed for the full reservation even if you use less, since it isn’t shared.
The “user priority” is actually just a record how much you have consumed lately (the billing numbers above). This number goes down with a half-life decay of 2 weeks. Your personal priority your share compared to that, so we get the effect described above: the more you (or your department) runs lately, the lower your priority.
If you want your stuff to run faster, the best way is to more accurately specify your time (may make that job can find a place sooner) and memory (avoids needlessly wasting your priority).
While your job is pending in the queue SLURM checks those metrics
regularly and recalculates job priority constantly. If you are
interested in details, take a look at multifactor priority plugin page (general
info) and depth-oblivious fair-share factor for what we
use specifically (warning: very in depth page). On Triton, you can
always see the latest billing weights in /etc/slurm/slurm.conf
Numerically, job priorities range from 0 to 2^32-1. Higher is sooner to run, but really the number doesn’t mean much itself.
These commands can show you information about your user and job priorities:
slurm s
list of jobs per user with their current priorities
slurm full
as above but almost all of the job parameters are listed
slurm shares
displays usage (RawUsage) and current FairShare weights (FairShare, higher is better) values for all users
sshare
Raw data of the above
sprio
Raw priority of queued jobs
slurm j <jobid>
shows <jobid> detailed info including priority, requested nodes etc.
tl;dr: Just select the resources you think you need, and Slurm tries to balance things out so everyone gets their share. The best way to maintain high priority is to use resources efficiently so you don’t need to over-request.
RSE work rotations
- 2024 Oct 08
Let’s say you want to start a Research (Software) Engineer team in your own unit. How do you set your new hires off on the right path? A proposal is outlined below.
This is a companion post to Future RSE collaboration in Finland.
You need to find the right person to hire for the role. Most likely, this means someone with the skills you need but the mindset to transition from their own work to making other work possible. You can find hiring resources on the Aalto RSE page and some brief thoughts in the companion post Future RSE collaboration in Finland.
Let’s say you have hired someone. What’s next?
This proposal is much easier for someone inside of Aalto University than outside, but possibly could be negotiated for others.
Your new hire works as part of the existing School of Science RSE team initially, perhaps ~1 year.
The hire is paid, organizationally supervised in, and sits in your own unit. It is absolutely critical that they maintain close connections to your own unit, the membership in our team is only virtual. (Our team is remote-first, so this is easy).
They focus on projects from your own unit, but as part of our daily flow. This could mean asking your audience to join our SciComp garage for help and requesting that new big projects come via our project management systems.
Your new hire will learn all about how we work.
Your new hire will experience a tremendous diversity of projects and work with experts on them.
After the initial ~1 year period, we sit down and decide what is next. Does your new hire stay working as part of our team (with a greater focus on your own unit’s projects)? Or do they split off and start doing their own thing in your unit? Or some combination?
This gives you the most important part of our onboarding and training. There is no better way to develop the right mindset. If we split later, your staff will know who to ask for harder problems that come up later.
If this sounds interesting to you, contact the author of this article
(first.last@aalto.fi or various chat systems).
Future RSE collaboration in Finland
- 2024 Oct 08
The Aalto University School of Science has a successful Research Software Engineering service serving the whole university. This service has proven its value and there are an increasing number of questions of how others can form their own teams in Finland and work together. This post gives some thoughts on the matter.
This page is the opinion of the author and not Aalto itself. It’s not
an open offer for collaboration. The author is happy to help with any
questions you may have (first.last@aalto.fi or various chat
systems).
Universities have academics: the traditional core, making ideas and new results. Much research, even not “computer science”, needs computational tools. However, the skills needed even for basic computation can be so complex that not all academics can master it to do cutting-edge research. A Research (Software) Engineer (RSE) can bridge that gap: academics focus on their primary work, and the RSE makes the computing seamless.
For more info, see the Aalto RSE site. This is not that different from research engineers supporting complex physical equipment.
We’ve found there are plenty of qualified people to hire. The harder part is mentoring them to transition from a researcher (focused on single projects with emphasis on own publications) to supporter (supporting a wide variety of people with respect and compassion). This transition needs active mentoring.
See the companion post about work rotations for RSE mentoring - if you are in Aalto University then start there.
You should decide if you want (a) wide-ranging support which may include helping with basics or (b) specialist support for a limited audience. I would argue that our most important impact is (a): this has gotten us the most benefit overall, and a steady stream of more advanced projects as work advances.
Let’s say you want your own RSE team at your own organization. How can you and Aalto RSE work together?
Even without joint funding, some of us Aalto people would be happy to talk and give some advice, and be part of a broader general network. For example:
How our team works, what makes it work, advice for your team
Joint RSE seminars to build skills, for example as part of FCCI Tech (aka the SciComp Tech series), Nordic-RSE seminar series, or something new. Both of these are good for professional development and community.
All the advice and practices on the Aalto RSE site.
Professional networking and so on.
However, without funding, Aalto needs to focus on its own work.
With joint funding, it might be possible to make a collaboration.
Any higher level collaboration needs to be discussed with management. Assuming these discussions go well, we might join a collaboration together so that we can actually share projects between the team. There should always be a strong local presence, because that gets the best value. This opens more possibilities.
The more experienced or larger teams could provide:
Mentoring possibilities for new research engineers and their teams (see RSE work rotations).
A base for professional networking.
A larger base of knowledge, for more advice and help with specialist problems. A very important part of our team is that for almost any problem, someone has seen it and can solve it quickly. Then we train others to solve it.
Joint support sessions such as our SciComp garage, which allowed a wider support base for problems, covering the previous point.
The newer or smaller teams could provide:
Funding via some joint project.
More staff around to help fill in the gaps when needed (these staff also get training in these projects they experience).
Specialty domain knowledge (both for support of academics and for professional development).
A collaboration with larger funding could have a joint project flow: there is one place to submit new projects requests, and the right people in any organization will work on them.
We would welcome observers in our support sessions, especially from other staff at Aalto. The Nordic-RSE chat is also a good way to ask questions and see what we are up to for those outside Aalto University.
We know of various opportunities being considered for national (Finland) or international RSE collaborations. The above are some basic thoughts, but any model would be tailored to the actual funding and partners. There is definitely a benefit to starting off together.
For more information, contact the author at first.last@aalto.fi
and read Research Software Engineers for more info.
Triton v3 is now default
- 2024 May 06
Triton has a major update. You can read our previous info about this at Preparing for new Triton, and our “what has changed” in Triton issue #1593.
You might get SSH host key warnings.
It has the same name, and importantly the same user accounts and data, but all the software and operating system is changed. In particular:
All software modules are different
Any software which has been complied will need to be re-compiled.
Triton’s previous operating system was released in 2014. Security support runs out at the end of 2024 May, and it has to be updated. Stability is good for research, so we try to reduce the number of changes (compare)
We realize that a change is very disruptive and painful, especially since the expectation is that Triton never changes. But an old operating system makes problem for users too, and they have gotten more and more over the years.
Most of the transition for different types of software is described in Triton issue #1593.
Triton v3 SSH host key warnings
- 2024 May 06
When updating Triton, many users will get a message like this (or similar things if you use other SSH clients like PuTTY):
SSH (Secure SHell) is made to be secure, and that means one it
verifies the server you are connecting to via its ssh host
key. The representation of this key is the fingerprint, like
SHA256:OqCehC2lbHdl8mYGI/G9vlxTwew3H3KrvxKDkwIQy9Y. This means
that the NSA or someone can’t intercept the connecting and get your
password by pretending to be Triton. This is a good thing.
OpenSSH (the command line program on Linux, MacOS, Windows) saves
these connection IDs (fingerprints) in
$HOME/.ssh/known_hosts. Other programs may store the keys
somewhere else.
The warning looks scary but the first thing to ask is “should the server I am connecting to have changed?”. If you have been directed to this blog post, then probably yes, it has. You should always think if the fingerprint should change, and if there is no reason for them to have changed, contact your administrators. You can usually verify the keys online, for example Triton ssh key fingerprints.
If you are on command line OpenSSH (Linux), it will propose a command that will remove the old host key:
For other programs, follow whatever prompts it might give to replace the host key fingerprint.
When you get a “The authenticity of host ‘triton.aalto.fi’ can’t be established”, verify the SSH key fingerprints that are presented, then click “yes” to permanently save them (until they change next, they can always be updated). The fingerprints for Triton v3 are:
Research Software Engineer project funding: what’s been working
- 2024 Feb 21
The “Research Software Engineer” service provides technical collaborators for researchers to complement their scientific knowledge. Read about Aalto RSE here. The idea of this service was that it would be available to everyone, but some projects who made extensive use would fund it themselves.
If you are a group leader reading this, Aalto RSE can help you release research code, debug it, make it reusable, rescue old code from former members and make it usable again, make it run on our cluster or CSC’s clusters, manage data, prepare data for easy use, and so on. If it’s not long (less than a month), our work is free, if it’s more than a month, the below applies.
When we started, we hoped for around 50% project funding. The idea was that a lot of the funding for the service would come from the research projects themselves. This hasn’t really worked out so well, because a) we accomplish the vast majority of our projects quickly, in less than a few weeks, and b) finance would understandably not like to deal with small transactions for small amounts of time.
What actually happened was that we basically have received only a small amount of the project funding we would have wanted. On the other hand, this also means we have supported a far wider variety of projects than we would have otherwise. It also means we are better accomplishing our other goal: tactical support right where and when it’s needed most, with the least amount of administrative overhead. This actually better matches our mission of helping the researchers who need us most.
For any long projects (more than a month or so), we still follow do our original plan: we can receive funding from grants (or basic funding) to do long-term projects. This is usually 40-80% of a RSE’s time, spread out over more than a month (and it can also be bursty: lots of work at some times, waiting for the next task at other times). We have done this for projects, and we know we can do it in the future.
But there’s another thing that has worked well: retainer-type funding instead of project-based funding. You have extra funding that needs to be used? You know your group needs support but you can’t name a single specific project to use all the time? Hire RSEs on long-term retainers and we’re there for you as needed. You will always get priority for all the quick questions you have (in SciComp garage or otherwise), and you get the highest priority for your medium projects, we can attend your other group meetings, and so on. As your team wants, we’ll make high-impact improvements here and there. This could be (for example) anywhere from 10-40% time over a long period.
We have worked out how to do both one-off projects and retainers with Finance. As for as external funders are concerned, our staff count as researchers, so we can use any funding you might have.
If you think you have a project or want us on retainer, let us know: Research Software Engineers or For researchers and research groups.
This is a valid questions. Compared to many RSE groups, we seem to be focusing on many small questions for a broad audience that knows a lot about the problems they need to solve. Thus, we can come in to something already set up well, provide help, and mostly back off and be available for maintenance long-term. The units that fund us (schools, departments) have been happy with this, so we’ve kept it up. On the other hand, we are pretty fast. There have been projects where a summer worker was going to be hired, that we could end up doing (learning the framework + all the main tasks) in two weeks. The way we work together as a team also makes things quite fast. Thus, a project has to be quite deep in order to exceed a month of work.
Kickstart 2023 wrap-up and thoughts for the future
- 2024 Feb 15
Our kickstart course came and went with very few problems. This post summarizes our general thoughts on the course and its format.
If you want to join the course next year (as an attendee, or as an organization who will send your learners to us (and maybe co-teach) follow us on Mastodon. This is the third year we’ve done the livestream format, and it’s not likely to stop anytime soon.
This was originally written in June 2023 but publication was forgotten until 2024.
The course has run since around 2015 or so. Until mid 2020, it was always in-person only. Until (and including) 2022, it ran twice a year, January and June, but now it runs only in June (increased availability of videos + the material compensates). It runs in June so that it aligns with new summer research interns starting. Until around 2020, it was mostly about using the HPC cluster at Aalto University, but since then there has been more emphasis on day 1 covering generic skills needed for scientific computing and the big picture of things.
Our general feedback remains quite positive. Our streaming + coteaching + collaborative notes format is still well received, and there seems to be little reason to go back for courses of smaller scale. Instead of just lectures, written material (tutorials in info on scicomp.aalto.fi) + livestream + videos is a good combination.
There is never enough time - not much else to say. Each year there is a different trade-off between how much we cover and how brief we are. (There are always people who say we should go more in-depth, and some who say we go too much in-depth. Such is life.)
Repetition is good, but not when it’s a sign that we can’t stop talking and keep saying the same thing over and over. The best lessons seemed to be the ones that were taught most quickly, since it has a high density of new information. We should strive to make more lessons faster, and leave details to the reading.
Because the teachers also do support, for anything difficult, we can easily tell learners: “Do what you can, come by our SciComp garage to ask for help with anything else. This overall reduces the demands from teaching: a person doesn’t have to know everything, but know enough to get started and to know when they may need more help for more advanced tools. This really is good for both of us.
As usual, we expected our learners to read our shell crash course in advance. We also had a new tutorial on using the cluster from the shell. This helped some, but it was still a problem.
Reflection: this will always be a problem in any course that has a wide enough audience. We should accept and provide positive support for those not ready, and not try to exclude them. It’s OK to see a course and then strive to get the prerequisites later.
Internally, we had this thought of dividing the course in two: a basic part at the start of the summer, and an advanced part at the end of the summer - since brand new researchers may have trouble understanding everything. On the other hand, the fact we have videos means that people can come back and review the material when they are ready. So in some sense, learners can divide the course however they would like by stopping when they think it’s no longer necessary and coming back. This could be mentioned more explicitly in our introductions.
Attendance goes down day-by-day. This is definitely OK - it doesn’t hurt anyone. It’s expected that day 1 was suitable for the most people (even those not doing HPC work), and then the course topics got continually more specific as we went further and further.
As mentioned above, this is even be expected and encouraged - better to have someone attend day 1, than not.
Our exercises are quite basic overall, but we got few complains about this. Basic exercises are better than something too advanced or realistic, that requires many things to come together.
This year, we tried to have a complete solution for every exercise (script and/or commands), even if it’s directly said above in the lesson. This seemed to be good, since for people very short of time, they still have some chance to copy and paste and do the exercises. For those passively following, they can at least see what would have been done.
Day 3 / end of course feedback positive feedback (o is the way a
person votes for/agrees with that option:
it’s great that the material is so easily accessible also after the course to go through things in my own pace again oo
Really good format with the streaming and the shared document for questions. ooooo
The cat kept me focused in the lecture
Live interaction with the instructes were very helpful and exercises were nice
I really appreaciate the instructors took the time to explain the jargons, instead of just letting them fly around. o
The fact that the instructors were really nice contributed to the good course experience. Thanks for that! o
(day 1) After studying remotely for 1,5 year and having lots of online classes, I highly appreciate the amazing audio quality here. Many thanks for that!
(day 1) The framework is better than any other workshop I’ve ever attended - in terms of interaction and audio quality. HackMD is great.
(day 1) The (twitch) vertical screen thing is genius and should be used in way more (online) lectures o
Most common negative feedback: not enough time! In fact, that’s almost only thing to improve. Except we can’t, so I think we win pretty well. And videos/material allows follow-up.
How we did summer kickstart 2021