README.md

# Project: a new mix template for projects

This is an alternative for `mix new`, creating what I feel is an
easier to read and maintain set of basic files.

You use it in combination with the `mix gen` mix task, which you will need
to install.

## Installation

This template is installed using the `template.install` mix task.
Projects are generated from it using the `mix gen` task.

So, before using templates for the first time, you need to install these two tasks:

    $ mix archive.install mix_templates
    $ mix archive.install mix_generator
    
Then you can install this template using

    $ mix template.install gen_template_project
    

## Usage

To create a basic project, with no supervision and no application, run:

~~~
$ mix gen project «project_name»
~~~

This will create a subdirectory called `project_name` containing your
seed project. By default this project will be created under your
current directory; you can change this with the `--to` option:

~~~
$ mix gen project «project_name» --to some/other/dir
~~~

### Variants

To create a project with a top-level supervisor contained in an
application callback, use the `--sup` option. 

~~~
$ mix gen project «project_name» --sup
~~~


## Background

You probably use `mix new` and/or `mix phoenix.new` to create new Elixir
projects. 

I never really likes the code these generators created. The layout made things
hard to read, and even harder to change. For example, the `mix.exs`
file looked like this:

~~~ elixir
defmodule Myapp.Mixfile do
  use Mix.Project

  def project do
    [app: :myapp,
     version: "0.1.0",
     elixir: "~> 1.4",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps()]
  end

  # Configuration for the OTP application
  #
  # Type "mix help compile.app" for more information
  def application do
    # Specify extra applications you'll use from Erlang/Elixir
    [extra_applications: [:logger]]
  end

  # Dependencies can be Hex packages:
  #
  #   {:my_dep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:my_dep, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
  #
  # Type "mix help deps" for more examples and options
  defp deps do
    []
  end
end
~~~

Let's look at a couple of problems.

The various lists are written in a really compact form:

~~~ elixir
[app: :myapp,
 version: "0.1.0",
 elixir: "~> 1.4",
 build_embedded: Mix.env == :prod,
 start_permanent: Mix.env == :prod,
 deps: deps()]
~~~

The indention is a unconventional single space, the entries are in an
apparently random order, and the layout makes it hard to distinguish
keys from values.

So, as a first iteration, I'd change this to:

~~~ elixir
[
  app:     :myapp,
  version: "0.1.0",
  deps:    deps(),
  elixir:  "~> 1.4",
  build_embedded:  Mix.env == :prod,
  start_permanent: Mix.env == :prod,
]
~~~

This moves the most commonly changed things to the top and aligns the
values. It also has the list ending with a comma. This makes no
difference to the internal representation of the list, but makes it a
lot easier to change the order of entries and add new lines.

Next, let's remove the duplication:

~~~ elixir
in_production = Mix.env == :prod
[
  app:     :myapp,
  version: "0.1.0",
  deps:    deps(),
  elixir:  "~> 1.4",
  build_embedded:  in_production,
  start_permanent: in_production,
]
~~~

All very well, but why are we exposing people to `build_embedded` and
`start_permanent` as it they were as important as the application name
and version? In fact, do you even know what they do? (I didn't until I
started looking into all this.)

So let's split out the important (and changeable) stuff, and give it
its own section in the mixfile.

~~~ elixir
defmodule Myapp.Mixfile do
  use Mix.Project

  @app     :myapp
  @version "0.1.0"
  
  @deps    []
  
  # ------------------------------------------------------------
  
  def project do
    in_production = Mix.env == :prod
    [
      app:     :app,
      version: @version,
      deps:    @deps,
      elixir:  "~> 1.4",
      build_embedded:  in_production,
      start_permanent: in_production,
    ]
  end

  # Configuration for the OTP application
  #
  # Type "mix help compile.app" for more information
  def application do
    # Specify extra applications you'll use from Erlang/Elixir
    [extra_applications: [:logger]]
  end
end
~~~

Now let's think about the `application` function. Every application
out there has the Logger started. How many use it? I'm guessing less
than 50%. But we normally just leave it in because it seems like it's
needed. It also doesn't help that the comments don't really make it
clear what `extra_applications` is actually for.

So let's cut this down a little:

~~~ elixir
# Type "mix help compile.app" for more information
def application do
  [
    # extra_applications: [:logger]
  ]
end
~~~