First version of BeginnersGuide and other doc changes
This commit is contained in:
parent
a40d8f2e8c
commit
f2c853821c
238
BeginnersGuide.md
Normal file
238
BeginnersGuide.md
Normal file
@ -0,0 +1,238 @@
|
||||
# Beginners Guide
|
||||
|
||||
We are coming up to RailsGirlsSummerOfCode, so i wrote this document for people with
|
||||
very little coding or ruby experience. It can be used by other people as a check-list,
|
||||
because basically anything in here is assumed when working on RubyX.
|
||||
|
||||
# Tools of the trade
|
||||
|
||||
I just want to introduce the main characters, what you need, maybe some extra.
|
||||
Details for installing or using software are abound on the net, so i am not getting
|
||||
into specifics, platform issues or the like. Just an overview that you may not find
|
||||
on the net.
|
||||
|
||||
## Terminal
|
||||
|
||||
The terminal and editor are still the two main tools you need. A terminal is a program
|
||||
that interprets typed input and starts other programs. The interpreters are called
|
||||
shells, bash (Bourne Again SHell) is popular, but anything you have is fine.
|
||||
|
||||
The shell starts when you start a terminal (window or tab) and usually reads somehting
|
||||
like .profile, or .bash_profile , where environment variables may be set. These
|
||||
variables, usually with capital names, influence the behaviour of programs. The most
|
||||
import one is probably the PATH variable, that determines where program executables
|
||||
are searched.
|
||||
|
||||
Don't fuss in the beginning which terminal you use, anything is fine for starters.
|
||||
|
||||
When i talk about commands, i mean typing those commands in the terminal.
|
||||
|
||||
## Editor
|
||||
|
||||
Off course you need an editor to edit program files. The most important thing here is
|
||||
that it supports colour highlighting for ruby. It may be an IDE like RubyMine, vim, or
|
||||
i use atom. It does not really matter, as long as you know how to use it.
|
||||
|
||||
## Ruby, maybe with versions
|
||||
|
||||
There are two main ruby implementations, called MRI (Matz Ruby implementations) and
|
||||
JRuby (Java Ruby), we will use MRI.
|
||||
|
||||
There are several versions of MRI, though that used to matter more than it does now.
|
||||
Anything over 2.4 is fine for RubyX.
|
||||
|
||||
Because version differences were bigger, and in a professional environment it is
|
||||
essential to know the exact version on is using (in development and production)
|
||||
ruby version managers have been developed. There are rbenv and rvm , but since
|
||||
you don't really need them i will leave it at that.
|
||||
|
||||
## Gems
|
||||
|
||||
Gems are packages of ruby code. After all, any meaningful software will rely on other
|
||||
software, and so gems have been with ruby from the start as a way of packaging code.
|
||||
|
||||
Eg rubyx is a gem, and you can see the package definition in rubyx.gemspec in the root
|
||||
folder.
|
||||
|
||||
gem is also a command to manage gems. A version of gem (the command) will come with
|
||||
any ruby installation. gem is used to manage single packages, but for a project
|
||||
we usually need many gems, and this is where bundler comes in.
|
||||
|
||||
## Bundler
|
||||
|
||||
Bundler is a program (a gem actually) to manage all the gems a project needs. The
|
||||
problem it was made to solve is this: Say you need 10 gems for a project. Those 10
|
||||
gems all have dependencies of their own, so really you may need 20-40 gems.
|
||||
If not managed, different developers and production systems will have slightly
|
||||
different versions of gems. This leads to very hard to track errors, a nightmare
|
||||
basically.
|
||||
|
||||
A Gemfile is the bundlers way of specifying a projects dependencies. Bundler
|
||||
(using the command bundle install) then resolves all dependencies and their
|
||||
dependencies and installs all the needed gems.
|
||||
|
||||
Bundler also creates a Gemfile.lock to record all the gems that are needed. This file
|
||||
is usually checked in and will ensure that every developer has the same gems.
|
||||
|
||||
Only when the Gemfile is changed, or one wants to update gems by hand, does bundle
|
||||
install need to be run again.
|
||||
|
||||
## Git
|
||||
|
||||
Version control has always been essential to coordinate the work of many people,
|
||||
and git is arguably the best tool for the job. So you need to install it and get
|
||||
to know the basics, at least clone, commit, push, and basic branches.
|
||||
|
||||
After installing MRI and bundler you need to clone the rubyx repository.
|
||||
Go to the directory and bundle (or bundle install, sama sama)
|
||||
|
||||
Then you can run "ruby test/test_all.rb" to determine that everything is working as it
|
||||
should. If it does, you are ready to start development.
|
||||
|
||||
# Development process
|
||||
|
||||
Once you have a working environment, you'll be wanting to code. So this section is
|
||||
about the basic loops we go through as developers, the recurring tasks that make
|
||||
up a programmers life. I'll try to avoid jargon and rather explain why we do what we do.
|
||||
|
||||
## Edit => Save
|
||||
|
||||
The most basic cycle is undoubtedly edit and save. You edit some part of the program
|
||||
and save your work. There are some details to consider about the formatting and style,
|
||||
in the [Code Style](CodeStyle.md).
|
||||
|
||||
There are two basic needs to do this basic coding:
|
||||
- you need to know what to edit, what it is you want to achieve and how to achieve it
|
||||
- having finished (saved) you need a way to know if you have achieved what you set out to do
|
||||
|
||||
The "how to achieve it" part is the skill of programming. Like all skills, developing
|
||||
this skill is a process and takes years, so i'll leave it at that.
|
||||
|
||||
What you want to achieve is up to you. Your imagination for the new. Your ability to
|
||||
find bugs. Or your willingness to do what others have found worthy of doing (issues).
|
||||
This is explained more in the next section.
|
||||
|
||||
So then we come to that crucial part of knowing when you achieved your goal. This has
|
||||
been at the crux of programming since the dawn, and the most widely agreed upon way is
|
||||
off course testing. Everybody agrees testing is the way, just how much is in dispute.
|
||||
It's like being healthy: everybody agrees in principle, but many still smoke, or
|
||||
eat meat or milk products (clearly shown to be unhealthy)
|
||||
|
||||
## Testing (or edit => save => test)
|
||||
|
||||
RubyX is very clear on the topic: all code needs tests. All new code needs new test.
|
||||
Every bug-fix needs more tests. Tests are the only way we know things work, and
|
||||
since RubyX produces programs as it's output (which should run correctly), we need
|
||||
to know doubly well that everything works. Both the RubyX code, and the generated code,
|
||||
must work, ie be tested. Some may call this TDD extreme, i call it common sense, and
|
||||
find it is the best way to work.
|
||||
|
||||
Specifically RubyX uses minitest, and has several layers of tests under the test
|
||||
directory. Generally speaking, test files contain ruby code called tests.
|
||||
This code exercises the source code and asserts (tests)
|
||||
assumptions to be correct. Minitest provides a base Test class to derive from and
|
||||
about ten different assert methods to assert assumptions. Methods of the class must
|
||||
start with test_ and each such method is called a test.
|
||||
|
||||
RubyX currently has over 1700 tests with almost 15000 assertions.
|
||||
At about 7k lines of code, that is roughly 2 assertion for each line of code. this
|
||||
should give you an idea how important testing is in RubyX.
|
||||
|
||||
## Automated testing (edit, save , autotest) or guard
|
||||
|
||||
Guard is a tool to run tests automatically. Similarly to bundler, Guard defines
|
||||
a Guardfile to define which tests should be run, and a command-line tool (guard)
|
||||
to run them automatically.
|
||||
|
||||
Basic tests mirror the same directory structure as the code in the test
|
||||
directory. Basic (or unit) tests live in files with the same name as the source
|
||||
code file name, with a "test_" prefix, in a shadowed directory. Eg for a file
|
||||
/lib/parfait/word.rb , there will be a file in /test/parfait/test_word.rb .
|
||||
|
||||
The Guardfile defines conventions like this, in code. So there
|
||||
is a basic rule in the Guardfile stating that when a source file changes
|
||||
the equivalent test file should be run. Other rules may be added easily,
|
||||
as a Guardfile is really just ruby code, working against the guard api.
|
||||
|
||||
The way to use guard is to have a terminal open and start the guard command.
|
||||
Guard will listen for changes, and once a file is saved *automatically* run
|
||||
affected test files.
|
||||
|
||||
This way we're back to edit, save, the shortest possible loop. Only when all tests
|
||||
are green, and there are enough (new) tests to cover the code, can you move on to the
|
||||
next phase, sharing your code.
|
||||
|
||||
# Contribution process
|
||||
|
||||
Open source is all about sharing code. It maybe for the greater good, or just fun,
|
||||
but it is working together in a coordinated fashion. Git (with commit rights) is
|
||||
what makes the coordination easy, some might say possible.
|
||||
|
||||
You start with a clean environment, either you just cloned, or pulled from github.
|
||||
|
||||
There are several ways to find what you want to work on, but all roads lead to
|
||||
github issue. You either find an existing one, or create one. Don't start
|
||||
work on something that has no issue, and the best way is to make your intention
|
||||
clear, by commenting on the issue.
|
||||
|
||||
## Topic branches and issues
|
||||
|
||||
Once you have a topic (and a github issue to go with it) you want to start coding.
|
||||
But don' just yet. To manage you changes with others, it is best to create what is called a topic branch. Branches are very cheap in git (very little resources required),
|
||||
and make it so much easier to manage the code. It is really not advisable to
|
||||
skip this step (read: your contribution may not be accepted, which really is in
|
||||
no-ones interest, least your own) unless it is a tiny, non-controversial change
|
||||
like a typo.
|
||||
|
||||
git checkout -b 65_my_bugfix
|
||||
|
||||
This is the command to start a new (topic) branch. You'll want to start with the
|
||||
github issue number and add a short description for the task.
|
||||
|
||||
## work on the issue / branch
|
||||
|
||||
As described above, you can now edit the code and tests to work on the issue.
|
||||
You may use the github issue for discussion or help. You can also push the branch
|
||||
to github and collaborate on the code. Or have someone review it.
|
||||
|
||||
Use guard, write minitests, edit (according to code guidelines) until happy.
|
||||
Commit, push and create a pull request.
|
||||
|
||||
## about committing
|
||||
|
||||
Regular small commits make for the best workflow. Where the line goes is a little
|
||||
bit experience, but often it is no more than 5 affected files, no more than 50-60
|
||||
lines affected. For a professional, 1-4 hours, for a beginner more.
|
||||
|
||||
Commits should be grouped around topics. Ideally (but not always) a commit takes the
|
||||
whole project back to green (all tests working). But this is not always possible
|
||||
and should not keep you from making commits. Commit when you have made some kind
|
||||
of milestone, some small but cohesive change.
|
||||
|
||||
Usually beginners tend to make to large commits, but just to mention that there is also
|
||||
a lower limit. Technical a single line may be a commit, but it would have to be a very,
|
||||
possibly very very important line. Ie a critical fix, a version update know to break
|
||||
things.
|
||||
|
||||
Usually i don't commit changes under 10 lines. If they happen, i band them together
|
||||
with the next commit, possibly mention them in the (then multi-line) commit message.
|
||||
|
||||
About commit messages, they should describe the change in passive mode, as if the
|
||||
commit made the changes. Ie "Fixes bug 36" , or "Adds method XXX to YY"
|
||||
|
||||
## pull request
|
||||
|
||||
A pull request is you asking the project owner (or anyone with commit rights) to
|
||||
accept your work and merge it into the main (master) branch.
|
||||
|
||||
For small issues and especially when it has been discussed, this is a press of a button
|
||||
for the project owner. But for larger changes, he/she may want to pull the
|
||||
branch to their machine, look at it and consider.
|
||||
|
||||
If there are changes to be made, more discussion may follow. This may result in
|
||||
you having to make more changes and so the process continues. This is why topic
|
||||
branches are so important, to keep this kind of back and forth out of the main
|
||||
branch and maintain a working / clean master branch.
|
||||
|
||||
After a pull request has been accepted, you go back to the master branch, pull
|
||||
changes, and start again with a new topic. And so life for the developer continues :-)
|
50
CodeStyle.md
50
CodeStyle.md
@ -14,6 +14,41 @@ While ruby allows the omission of brackets even with arguments, i try to avoid t
|
||||
of readability. There may be an exception for an assignment, a single call with a single arg.
|
||||
Brackets without arguments look funny though.
|
||||
|
||||
### Method length
|
||||
|
||||
Methods should not be more than 10 lines long. It points to bad design if they are,
|
||||
spaghetti code, lack of abstraction and delegation. This may seem extreme coming from
|
||||
other languages, and i admit it took me some years to see the light, but now it's pretty
|
||||
much that. Longer methods will have a very very hard time to get accepted in a pull
|
||||
request.
|
||||
|
||||
### No of arguments
|
||||
|
||||
Methods taking over 4 arguments are dubious. Actually 4 is already borderline. If a
|
||||
method actually needs that much info, it is most likely that a class should be
|
||||
created to hold some of it.
|
||||
|
||||
### Class length and size
|
||||
|
||||
On class length i am not rigid, but too large is a definitely a thing. More than 5-6
|
||||
instance variables probably means the class is doing too much and should be split.
|
||||
Also a total loc of more than 200-250 or method count over 20 is not a good sign.
|
||||
Especially when combined with struct classes that just hold data and have too little
|
||||
functionality, this may represent problems in pull request.
|
||||
|
||||
### Global and class variables
|
||||
|
||||
Global variables is one of the few design mistakes in ruby. They just should not exist,
|
||||
meaning they should not be used.
|
||||
|
||||
Use class variables only if you are sure you understand their scoping, specifically the
|
||||
difference between class variables and class instance variables. Lean towards
|
||||
class instance variables.
|
||||
|
||||
Since classes (and thus modules) are global, class and module methods are global.
|
||||
Use sparingly with good insight, as it ties the usage to the definition and
|
||||
oo benefits like inheritance are lost.
|
||||
|
||||
## Code style
|
||||
|
||||
### Module functions are global
|
||||
@ -21,8 +56,8 @@ Brackets without arguments look funny though.
|
||||
Often one thinks so much in classes that classes get what are basically global functions.
|
||||
Global functions are usually meant for a module, so module scope is fitting.
|
||||
|
||||
A perfect example are singleton accessors. These are often found clumsily on the classes but
|
||||
the code reads much nicer when they are on the module.
|
||||
A perfect example are singleton accessors. These are often found clumsily on the classes
|
||||
but the code reads much nicer when they are on the module.
|
||||
|
||||
### Code generators
|
||||
|
||||
@ -31,3 +66,14 @@ All names are resolved to registers, or index via Type. More readable code less
|
||||
As the example shows, in this case the module function name should be the instruction class name.
|
||||
|
||||
Singletons should hang off the module (not the class), eg Parfait.object_space
|
||||
|
||||
## Naming
|
||||
|
||||
Naming must be one of the most important and difficult things in programming.
|
||||
Spend some time to find good, descriptive names.
|
||||
In the days of auto-complete, short cryptic names are not acceptable any more.
|
||||
|
||||
When naming, remember to name what something does (or is), not how. A classic misnomer
|
||||
is the ruby Hash, which tells us how it is implemented (ie by hashing), but not it's
|
||||
function. In Smalltalk this was called a Dictionary, which is tells us what it's for,
|
||||
to look something up (with real-world reference, double points).
|
||||
|
24
README.md
24
README.md
@ -14,12 +14,12 @@ of the system, see below. The overhaul is done and rubyx produces working binari
|
||||
|
||||
Processing goes through layers: Ruby --> Sol --> SlotMachine --> Risc --> Arm --> binary .
|
||||
|
||||
Currently most basic constructs work to some (usable) degree, ie if, while,
|
||||
Currently most basic constructs work to some usable degree, ie if, while,
|
||||
assignment, ivars, calling and dynamic dispatch all work. Simple blocks, those
|
||||
that ruby passes implicitly also work (lambdas not).
|
||||
|
||||
Work continues on memory management, which turns out to be pretty basic to do just about
|
||||
anything, even counting to a million.
|
||||
Work continues on memory management, which turns out to be pretty basic
|
||||
to do just about anything, even counting.
|
||||
|
||||
## Layers
|
||||
|
||||
@ -83,26 +83,24 @@ Generating code (by descending above layers) is only half the story in an oo sys
|
||||
The other half is classes, types, constant objects and a minimal run-time. This is
|
||||
what is Parfait is.
|
||||
|
||||
Parfait has basic clases like string/array/hash, and also anything that is really needed
|
||||
Parfait has basic classes like string/array/hash, and also anything that is really needed
|
||||
to express code, ie Class/Type/Method/Block.
|
||||
|
||||
Parfait is used at compile time, and the objects get serialised into the executable to
|
||||
make up, or make up the executable, and are thus available at run time. Currently the
|
||||
methods are not parsed yet, so do not exist at runtime yet.
|
||||
|
||||
### Builtin
|
||||
### Macros
|
||||
|
||||
There are a small number of methods that can not be coded in ruby. For example an
|
||||
integer addition, or a instance variable access. These methods exists in any compiler,
|
||||
and are called builtin here.
|
||||
and are called macros here.
|
||||
|
||||
Builtin methods are coded at the risc level with a dsl. Even though basically assembler,
|
||||
Macros are coded at the slot_machine level with a dsl. Even though basically assembler,
|
||||
they are
|
||||
([quite readable](https://github.com/ruby-x/rubyx/blob/2f07cc34f3f56c72d05c7d822f40fa6c15fd6a08/lib/risc/builtin/object.rb#L48))
|
||||
through the ruby magic.
|
||||
|
||||
I am in the process of converting builtin to a simple language on top of SlotMachine,
|
||||
which i'm calling SlotLanguage. But this is wip.
|
||||
The Macros are found in lib/slot_machine/macro .
|
||||
|
||||
## Types and classes, static vs dynamic
|
||||
|
||||
@ -145,6 +143,7 @@ commands that have a linux baked in, qemu-arm in case of arm. So running
|
||||
machine where qemu is installed with *qemu-arm ./hello* .
|
||||
|
||||
On my fedora, the package to install is "qemu", quite possible on mac with homebew, too.
|
||||
The web-page has some more [info](http://ruby-x.org/arm/qemu.html).
|
||||
|
||||
### Interpreter
|
||||
|
||||
@ -161,7 +160,7 @@ out what is going on, and in finding bugs.
|
||||
|
||||
The above architecture is implemented. At the top level the RubyXCompiler works
|
||||
pretty much as you'd expect, by falling down the layers. And when it get's
|
||||
to the Risc layer it slots the builtin in there as if is were just normal code.
|
||||
to the Slot layer it slots the macros in there as if is were just normal code.
|
||||
|
||||
Specifically here is a list of what works:
|
||||
- if (with or without else)
|
||||
@ -175,7 +174,8 @@ Specifically here is a list of what works:
|
||||
|
||||
## Contributing to rubyx
|
||||
|
||||
Probably best to talk to me, if it's not a typo or so.
|
||||
Probably best to talk to me, if it's not a typo or so. For beginners i have written a
|
||||
[BeginnersGuide](./BeginnersGuide.md) to start from zero.
|
||||
|
||||
I've started to put some github issues out, some basic some not so. Also there is a todo
|
||||
for the adventurous (bigger things, no BIG things).
|
||||
|
Loading…
Reference in New Issue
Block a user