On the October 30th, 2018 Technical Committee call the subject of the developer experience was raised (starting from a discussion on the audit log initializer resulting in so much CPU usage when using demo data - i.e. the developer workflow) leading to a more in depth discussion about the “typical” developer workflow, and what challenges people had.

I think this is important for us to follow-up on, and I like how a positive developer experience has been compared to positive marketing for the product (thanks @Wesley_Brown).

In an effort to continue the discussion, I want to summarize a few of the key points we made:

Not everyone runs the Ref Distro locally - some do, some dont

When not running Ref Distro it might be: It’s too slow or takes too much memory or for UI development it’s just unneeded (you can point UI at the back-end services on test). Otherwise it’s simpler/quicker to see the change on test.

When running Ref Distro it might only be done if it’s a change to demo-data or the work involves multiple services.

We have stunted our tooling by requiring everything, especially integration tests, to be run inside a docker container.

Some of our tooling has grown quite out-of-date (e.g. Spring Boot has moved on to version 2).

To start addressing some of these concerns, and to spur more discussion, I made a simple change to Reference Data so that you can run integration tests outside of the docker container by running ./gradlew integrationTest - it’ll launch Docker containers for PostgreSQL, Redis, et al and run the tests under your computer’s JVM, and this should work from IntelliJ as well. Give it a try and let me know what you think.

Of course this doesn’t address everything we raised. If I would define a set of work, I think that would be:

Prioritize work that reduces the system resources required to launch Ref Distro (e.g. audit log initializer)

Make it simple to make a change to a Service, and quickly test that in a Ref Distro.

Focus on supporting testing development tasks that run outside of a docker container - so that it’s easier/faster to use an IDE.

Start upgrading our tools / dependencies (I also started down this path, see the OWASP dependency report and also see which dependencies have newer versions by running ./gradlew dependencyUpdates).

Is this the work you’d focus on? The way that you’d prioritize it? What about the UI workflow? Lets start that discussion here and get it right. The better we define it here, the better everyone’s daily work flow should be.

Personally, I would go with the following order #3, #2, #4 and #1. The ability to easily run the tests from the IDE would be awesome as well as the ability to launch the ref distro quickly so checking changes would actually be faster than simply pushing them to the repository.

What about the UI workflow?

I’d say that developing the UI is pretty straightforward at the moment. It would definitely benefit from the ability to run ref distro locally so we could have a more stable environment when testing the features/bug fixes being implemented. What we could do is reviewing the documentation to see whether it is up to date and update it accordingly.

Overall, I’m happy that we’re thinking of moving in this direction but I would also like to say that going this way will lead us to a place where we no longer have a unified development environment that we’ve spent so much time and effort on.

I think it would be great to hear what people from new teams think about the development process because I - the developer which spent about 2 years in this project - don’t see too many problems with development process because basically, I adjusted myself to the existing process.

Prioritize work that reduces the system resources required to launch Ref Distro (e.g. audit log initializer)

In this case, we could simply create the required data for about 90% of the resources in our demo data. This would probably speed up the startup process and we could still verify that audit log initializer works fine. Nonetheless, I think we have too many microservices in ref-disto and because of that, a developer needs a very good machine to handle the project. Currently, I am working on a machine with 8 CPUs (Intel® Core™ i7-6700HQ CPU @ 2.60GHz × 8), 8GB of RAM and 16GB in the swap partition but still, when I run the ref-distro I can see that the system slowdowns or even freeze for about a minute or two. Maybe we could divide our ref-distro into smaller parts which will present OpenLMIS features because if a developer would like to check if changes in the requisition service are correct does he need the CCE service?

Make it simple to make a change to a Service, and quickly test that in a Ref Distro.

Why should I run ref-disto to verify my changes if tests (unit, integration, contract) should tell me if my changes are correct?

Focus on supporting testing development tasks that run outside of a docker container - so that it’s easier/faster to use an IDE.

Two years ago - when I started working on this project - I would say that this is a great improvement and it should be provided as soon as possible but now I am more skeptical about this. From what I remember we started using Docker to avoid problems with local development environments and situations when for some developers something does not work correctly. I remember that adjust to this new development process was hard for us but now with Docker, I am sure in 99% that my changes would work correctly on other machines.

Also if I understood correctly each time when I execute a Gradle task outside of docker environment, the task will automatically run a docker environment before and I am not sure if this will speed up the development process.

Start upgrading our tools / dependencies (I also started down this path, see the OWASP dependency report and also see which dependencies have newer versions by running ./gradlew dependencyUpdates ).

I would say this should be done in the first place. With new versions of tools/dependencies we would get new features and improve the security of our microservices.

What we could do is reviewing the documentation to see whether it is up to date and update it accordingly.

@ngraczewski would you mind writing this ticket and/or sharing the link to it?

ngraczewski:

Overall, I’m happy that we’re thinking of moving in this direction but I would also like to say that going this way will lead us to a place where we no longer have a unified development environment that we’ve spent so much time and effort on.

That wouldn’t be the intention. The authoritative environment would remain the dockerized one, we’d just also put more effort in ensuring tests may be run in IDE environments as well. Perhaps we need to make this clear in a convention document?

llewczynski:

I think it would be great to hear what people from new teams think about the development process because I - the developer which spent about 2 years in this project - don’t see too many problems with development process because basically, I adjusted myself to the existing process.

Maybe we could divide our ref-distro into smaller parts which will present OpenLMIS features because if a developer would like to check if changes in the requisition service are correct does he need the CCE service?

Good point, though I think we have three general, non-exclusive, paths:

Make it easy to deploy sub-sets of Ref Distro like you mentioned.

Reduce the resources that each service consumes.

Make it easy for a developer to work on a service running locally that is interacting with deployed services in the cloud (using a service mesh). It’s worth noting that this requires the biggest architectural change, and for it to be useful a developer still needs relatively decent internet access. This suggests this is interesting but perhaps a bit riskier than we’d like.

This is some great feedback all around so please keep it coming everyone.

Focus on supporting testing development tasks that run outside of a docker container - so that it’s easier/faster to use an IDE.

From my perspective, I don’t think this is much of a problem if it comes to running tests outside of Docker container. Starting docker container takes a couple of seconds and running test is one simple Gradle command where you can specify which tests do you want to run by copying the class name and optionally test name which I don’t find slower than clicking “run test” icon in IDE. I agree with others on that it seems late to try work on this after a couple of years, back then we supported docker idea by saying it will get rid of all dependency issues for different machines that developer are using. As I said it is not an issue for me, but if it is for others and changing it will not require much work I think it is OK to work on that.

joshzamor:

Some of our tooling has grown quite out-of-date (e.g. Spring Boot has moved on to version 2).

I think that it is will be nice to upgrade our dependencies, especially Spring Boot. If this will be focus for Team Parrot I would gladly work on that

joshzamor:

Prioritize work that reduces the system resources required to launch Ref Distro (e.g. audit log initializer)

This would be a good thing to work on together with making services easy to hot swap for checking changes on ref distro. For my machine, it takes about a minute or two to be usable again after the ref-distro start but I’m not running it that often. I remember the discussion on enabling debugging in ref-distro and the conclusion was that we should focus on adding more logging and focus on testing our changes and I would say the same thing here. Writing functional and contract tests while developing something should make changes in code less error-prone. Maybe together with making ref-distro easier to run locally, we should also try to make contract tests easier to run locally. I remember we made something similar for functional tests.

I’ll just re-iterate what I’ve already stated on the tech committee call. For myself, the biggest problem with the development experience is the need to go through multiple steps (build code, build image, update tag or compose file, start ref distro) and to wait several minutes to be able to verify even the smallest change I’ve made in the service.

I agree that TDD should generally guide us through the development, but eventually, you want to run your code and make sure that everything indeed works correctly. Some changes may also be difficult or impossible to verify with just tests.