exercism / elixir

Exercism exercises in Elixir.
https://exercism.org/tracks/elixir
MIT License
612 stars 396 forks source link

Convert exercises to mix projects #414

Closed amencarini closed 5 years ago

amencarini commented 6 years ago

After a chat with the active mentors on the Slack channel, a consensus emerged that the best way forward would be to have the exercises structured as mix projects.

The reasons given are: 1) It's how Elixir projects work in the real world, and students must be made aware that's the case when using exercism as a learning tool 2) mix already comes with the language so we aren't adding dependencies 3) It will execute any doctests you write 4) Dialyzer support can also be added to check typespecs 5) It lets you use mix test.watch 6) It lets you add dependencies easily (e.g, for debugging) 7) The current way of running tests makes using IEx.pry really complicated

As long as it doesn’t create incompatibility issues with how exercism works we'd like to start converting the exercises.

Could you please advise?

devonestes commented 6 years ago

So this has been brought up at least 5 times in the last two years, which tells me that folks are clearly pretty interested in this. In the past it has always been rejected in favor of making these exercises as simple as possible for beginners to get going with - no need to understand a build system or anything. However, since folks keep asking, I'm open to exploring this again. A few notes on your reasons given

1) This has always been the strongest argument, and I'm happy with it 2) Yeah, it's good that we don't need any dependencies 3) This isn't actually true. You still need to include doctest Module.Name in the test file to run doctests. 4) Dialyzer is extremely complicated to set up, and extremely slow to run for the first time. I would be generally cautious about recommending dialyzer for these exercises. 5) This to me isn't a huge benefit. They're small exercises with only a few tests. 6) Can you tell me some of the dependencies you're thinking of here? I'm unaware of any dependencies that are purely for debugging. 7) I've always found IEx.pry kind of complicated since it can't be used in a test, only in an IEx session. Using Mix won't change that.

So, there are definite pros and cons. Our Elixir community doesn't have nearly as many "true" beginners (almost everyone I've ever met or heard from came from another language), so maybe the focus on keeping things easy for those people might not have much benefit. However, by making this change, we'd potentially be making it harder for any "true" beginner to get started and have a great first experience with the language.

I'll leave this open for a little longer to see what other folks chime in with.

Cohen-Carlisle commented 6 years ago

I'd like to use mix as well. I think the extra files are worth it for the tools mix brings to the table, not to mention that it teaches people how to use elixir's built-in tooling.

NobbZ commented 6 years ago

I'm also strictly in favor of using mix, as it gives much more flexibility to the student and makes him able to easily play around with things as he likes.

Can you tell me some of the dependencies you're thinking of here? I'm unaware of any dependencies that are purely for debugging.

Well not debugging, but rarely used for production: benchee.

Also you get other tools as profiling ones with mix for free, as they are available in erlang and mix wraps them nicely.

Then we have dialyzer, once configured correctly and run for the first time, it will be fast enough for our small snippets. But to be honest, I do not think dialyzer is not worth the effort, as it works totally different than other typecheckers, and often does not complain about wrong return types.

This isn't actually true. You still need to include doctest Module.Name in the test file to run doctests.

But without mix you do not get them at all.

Anyway, doctests are not meant to test implementation, they are meant to test if the examples in the documentation are still current. Therefore they are not necessarily an argument for mix (neither are they against). I just wanted to clear with this misconception.

amencarini commented 6 years ago

One aspect that I only now thought of: back in the day I used Exercism to thrash out some Go, and Katrina commented saying "I think you haven't go fmted your code". Which to me is interesting: we might expect students to use a formatter if the command is the same as the one to run the code, but in Elixir's situation we don't except them to, because you format code with mix format, not elixir format.

I personally think the small extra cognitive cost is largely out-weighted by the best practices that can follow.

In any case, could we do an A/B test perhaps? We could have just one mixed project at the start of the curriculum and see what the dropoff rate is.

devonestes commented 6 years ago

Just wanted to add another comment to ping other watchers who might have wanted to weigh in on this and haven't gotten around to it yet 😉

devonestes commented 6 years ago

Ok, so after thinking about this and talking to a few other folks, I think this could be a good idea. I'd be happy to see a PR with some idea about how we implement this change, and then we can discuss specifics of the implementation there.

martinsvalin commented 6 years ago

Given how all tutorials on the web assume you're working with a normal mix project, not having mix might actually make it harder for true beginners. Test files don't look like what you come across elsewhere etc. I'm in favour of converting it all to mix projects.

Two questions:

1) How will this look in the code review interface on Exercism.io? If I extract some code into a separate module, what would be submitted? Only the main implementation file, meaning part of the solution is missing in the review interface? All files in the project, cluttering up the review interface? Or magically only the relevant files?

2) Should each individual exercise be a separate mix project, or should the Elixir exercism collection be a single mix project?

Separate projects creates a lot of extra files, but also let's you isolate each project and running mix test will run the tests for only that exercise.

Multiple mix projects (one per exercise) ➕ Convenient to run only the tests for one exercise. ➕ Using a dependency to solve a problem, it's clear it is only used for this exercise. ➕ If the answer to question 1 above is "the review interface shows all files", then this is really the only option.

Single project containing all exercises ➕ Reduces the number of redundant files (no duplicate config/config.exs etc). ➕ Convenient to run all tests for all exercises. ➕ Still pretty convenient to run only tests for one exercise, see below. ➕ Convenient to format all the code. ➕ Easier to reuse code between exercises

I did Advent Of Code in Elixir in 2015, 2016 and 2017.

In 2015 I didn't have a mix project. It was similar to how code is currently organized for Elixir on Exercism (actually, I believe I took inspiration from Exercism).

In 2016 I made separate mix projects. It felt a bit unwieldy, and I felt bad about all the boilerplate I added to the git repo for each one.

In 2017 I put all my solutions in one mix project, and listing lib would show files with a number prefix lib/01_inverse_captcha.ex. This felt nicer, but I had trouble with some problems that had high time complexity, meaning the test execution was slow. Running a slow test that was testing an unrelated exercise was annoying. I ended up tagging slow tests with @tag :slow, and a ExUnit.configure(exclude: [slow: true]) in my test_helper.exs. This meant I could still run all tests with mix test --include slow.

2017 with a single mix project felt best to me, and I actually went back to the other two years to restructure them a bit (in preparation for finishing the rest of the problems for those two years).

I do think I should have also module-tagged the test files per problem. Adding a @moduletag :inverse_captcha would have let me run only the tests for one problem with mix test --only inverse_captcha. So we should add module tags in each test file, with a comment explaining how to use it. It's an underused feature, and I bet a lot of experienced Elixir devs don't know about it. [Edit: running per test file isn't a problem, since you can run mix test test/specific_test.exs. No module tagging needed.]

NobbZ commented 6 years ago

Multiple mix projects (one per exercise)

This is the only way that is allowed by exercisms archtecture.

I extract some code into a separate module, what would be submitted?

Everything you specify will be submitted, eg: exercism submit lib/hello_world.ex lib/hello_world/helper.ex will submit these two files.

Du to a bug though, these names are currently not displayed on the webpage.

amencarini commented 6 years ago

I've created a PR of how the first two exercises would look like when using mix.

The only "oddity" when migrating the exercises was that mix new wants underscores, not hyphens, so I had to rename the exercise folder upon creation of the project. The rest should be self explanatory from the code and the description, but feel free to ping if you have further questions!

NobbZ commented 6 years ago

mix new --app hello_world hello-world should do it.

neenjaw commented 5 years ago

Exercises are now mix projects as of PR #480