Skip to content

Commit

Permalink
starting
Browse files Browse the repository at this point in the history
  • Loading branch information
joearms committed Mar 1, 2012
0 parents commit a4e794d
Show file tree
Hide file tree
Showing 70 changed files with 15,859 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/.gitignore
@@ -0,0 +1,10 @@
*~
*.tmp
\#*
erl_parse.erl
.eunit/*
deps/*
ebin
priv/*
*.o
*.beam
76 changes: 76 additions & 0 deletions src/Makefile
@@ -0,0 +1,76 @@
.SUFFIXES: .erl .beam .yrl

MODS := $(wildcard *.erl)
YRL := $(wildcard *.yrl)
CHAPS := $(wildcard *.chap)
BOOKS := $(wildcard *.book)
LOGS := $(wildcard *.log)

CWD := $(shell pwd)

../ebin/%.beam: %.erl
## erlc +warn_missing_spec -o ../ebin -W $<
## grep --silent --invert-match "_test"
erlc -o ../ebin -W $<

../ebin/%.beam: ../tmp/%.erl
erlc -o ../ebin -W $<

../doc/%.html: %.chap
@erl -noshell -pa ../ebin -s elib1_docmaker batch $< -s init stop

../doc/%.html: %.log
@erl -noshell -pa ../ebin -s elib1_chunks batch $< -s init stop

../doc/%.html: %.erl
./mkdoc $<

../tmp/%.erl: %.yrl
erlc -o ../tmp -W $<

../../pdf/%.pdf: %.chap
erl -s elib1_doc batch $<
fop -xml ../tmp/$*.xml -xsl chap2pdf.xsl -pdf ../../pdf/$*.pdf

# ../../html/%.html: %.chap
# erl -s elib1_doc batch $<
# fop -xml ../tmp/$*.xml -xsl chap2html.xsl -txt ../../html/$*.html

all: yecc beam html #chapHTML

test:
dialyzer -Wno_return --src -c "."

utest: beam
erl -noshell -eval "eunit:test(elib1_misc, [verbose])" -s init stop

edoc:
erl -noshell -eval "edoc:application(lib, \".\", [{dir,\"../doc\"}])" \
-s init stop

html: ${MODS:%.erl=../doc/%.html}

beam: ${MODS:%.erl=../ebin/%.beam}

yecc: ${YRL:%.yrl=../tmp/%.erl} ${YRL:%.yrl=../ebin/%.beam}

chapPDF: ${CHAPS:%.chap=../../pdf/%.pdf}

# chapHTML: ${CHAPS:%.chap=../../html/%.html}

books: ${BOOKS:%.book=../doc/%.html}

logs: ${LOGS:%.log=../doc/%.html}

clean:
rm ../ebin/*.beam
rm -rf *.aux *.beam
rm -rf *.log *.tmp erl_crash.dump

veryclean:
rm ../bin/* ../doc/* ../tmp/*





177 changes: 177 additions & 0 deletions src/best.notes
@@ -0,0 +1,177 @@
Best practice for writing documenting and testing code

I'd like to try and define "best practice" for writing documenting and
testing Erlang code. I want to use:

- only the tools supplied in the OTP release

So I use:

- eunit for unit testing
- the dialyzer for checking my code
- edoc for documenting things
- type specifications for specifying types

These tools do not completely "play together" in a satisfactory manner,
so I'd like to define what I thing is "best practice" and hope that by doing
so the tools will converge.

Let's suppose I want to define the good 'ol factorial. Here's a module
called elib1_best.erl. I've written it in such a way that it can be
processed by erlc,eunit,edoc and the dialyzer - read the footnotes
in brackets for an explanation.

-module(elib1_best). %% [1]

%% elib1_best: Best practice template for library modules [2]
%% Time-stamp: <2009-12-02 09:43:12 ejoearm> [3]

%%----------------------------------------------------------------------
%% Copyright (c) 2009 Joe Armstrong <erlang@gmail.com> [4]
%% Copyright (c) 2009 Whoomph Software AB
%%
%% Permission is hereby granted, free of charge, to any person
%% obtaining a copy of this software and associated documentation
%% files (the "Software"), to deal in the Software without
%% restriction, including without limitation the rights to use, copy,
%% modify, merge, publish, distribute, sublicense, and/or sell copies
%% of the Software, and to permit persons to whom the Software is
%% furnished to do so, subject to the following conditions:
%%
%% The above copyright notice and this permission notice shall be
%% included in all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%% SOFTWARE.
%%-----------------------------------------------------------------------

-include_lib("eunit/include/eunit.hrl"). %% [5]

-export([fac/1]). %% [6]


%% @doc fac(N) computes factorial(N) using a fast
%% iterative algorithm. [7]

-spec fac(integer()) -> integer(). [8]

fac(N) when is_integer(N), N >= 0 -> fac1(N, 1).

fac1(0, K) -> K;
fac1(N, K) -> fac1(N-1, K*N).

fac_test() -> %% [9]
6 = fac(3),
24 = fac(4).

%% Notes:
%% [1] - module on line 1
%% [2] - module comment
%% [3] - Time stamp auto generated by emacs.
%% Must be near start of file
%% [4] - Copyright (I always forget this, but adding a
%% copyright reduces the pain later
%% [5] - Needed for eunit
%% [6] - use export and NOT compile(export_all)
%% [7] - @doc comes first
%% [8] - -spec comes immediately *before* the function
%% [9] - test cases come immediately after the function

%% end of module
...

Now let's see what happens:

1) Compiling

erlc +warn_missing_spec -o ../ebin -W elib1_best.erl

./elib1_best.erl:0: Warning: missing specification for function test/0
./elib1_best.erl:44: Warning: missing specification for function fac_test/0

Best practice is to support type specifications for all exported
functions. But eunit magically adds a function test/0 and I really
don't want to have to add manual exports and type specs for
fac_test/0.

[A fix is needed to erlc here, OR eunit can add type specs,
I think the latter is better - erlc should not need to know about eunit]

2) Dialyzing

dialyzer --src elib1_best.erl
Checking whether the PLT /home/ejoearm/.dialyzer_plt is up-to-date... yes
Proceeding with analysis...
Unknown functions:
eunit:test/1
done in 0m0.32s
done (passed successfully)

This is ok - I could add eunit to my plt if I wanted ...
the dialyzer warns for missing functions so I don't need to run
xref

3) Documentation

I'll run edoc on everything in the current directory putting the
results in ../doc

> erl -noshell -eval "edoc:application(lib, \".\", [{dir,\"../doc\"}])" \
-s init stop

This works fine and ../doc/elib1_best.html has the documentation
but now edoc has not found my nice -spec declaration and thinks that
fac has type: fac(N) -> any()

Why: because edoc and erlc don't use the same type parser.

Current best practice is to use -spec (in code) and
not @spec (in edoc comments)

[A fix is needed here to edoc, to understand -spec's]

4) Testing

1> eunit:test(elib1_best, [verbose]).
======================== EUnit ========================
elib1_best: fac_test (module 'elib1_best')...ok
=======================================================
Test passed.
ok

Great ...

Now for questions.

1) Does this represent best practice? Is this the best way to
write code? - can anybody improve on this?

[And yes I know about quickcheck, but I'm only concerned
with SW in the OTP release]

2) If I write like this can I assume that one day edoc
and eunit and erlc will converge so that I get correctly displayed
types in edoc and no warnings in erlc etc?

3) Does anything else have to be fixed?

4) Improvements..

I can think of one. I have some code to convert .erl to
.html with correctly colored code and hyperlinks etc.
So I can "surf" the code. It would be nice to have hooks
into edoc so I can call this code

That's all for now ...

/Joe




35 changes: 35 additions & 0 deletions src/book.book
@@ -0,0 +1,35 @@
= An Erlang Library

This book describes an Erlang library called ''elib1''.

== Todo (formatting program)

<ul>
+ Add a diagram language (inline svg)
+ ~~Make the Book version~~
+ ~~Make compact lists, so I can leave out the blank line in paragraphs like
this~~
+ ~~add processing of ''footnotes''~~
+ Make commands for /bin
+ check that all list entries do not end with a dot.
+ Check that all list entries start with a big letter.
+ punctuation check.
+ ~~add "typographic quotes."~~
+ Nice to make paragraphs "clickable-editable" in the browser.
+ Add some nive paragraph hover effect that colors paras as we move over them. Makes text easier to read.
</ul>

== To do (programs)

<ul>
+ mysql full text searching and metadata
+ go through all old library adding good stuff (example topological sort)
+ javascript slide show from wiki markup
+ move over to GIT
+ xref
</ul>

<include chapter="design" />
<include chapter="ezxml" />
<include chapter="lorum" />

Empty file added src/chap2html.xsl
Empty file.

0 comments on commit a4e794d

Please sign in to comment.