This page lists some Best Practices that you should be aware of. They make it much easier for developers to cooperate.
Talk to the community.
Elody / The Legion of Devs is very much a communal project.
Use the forum to organize and discuss things before making larger changes. Who knows, maybe someone can give you tips that will save you a lot of time?
If you are new, head here and introduce yourself!
Build on what already exists instead of adding something completely new.
Before adding a feature, check if something similar already exists. Simply run a Scenario in Developer Mode and enter whatever information should trigger the Rule/Program you want to add. Check what Tags and Symbols are created. Can you use any of these for your own Rules?
For example, if you want to trigger a Program when certain keywords are mentioned, it is a good idea to rely on an existing Natural Language Program as a preprocessor instead of checking the user's input directly. This way your Rule will also be used if related keywords are mentioned that you might otherwise overlook.
Review each others' work.
Be aware that Elody will not use Rules you define until enough people have rated them and confirmed that they are useful. For this reason, it helps if everyone in a group looks over each others' work and rates it, to promote it to prominence more quickly.
Always add documentation to your Rules and Programs.
Make use of the [[Program/Rule/symbol:name/id]] pattern to create links to other Programs/Rules/Symbols. Other developers will thank you for the convenience.
Mention the strengths and weaknesses of your code, i.e. what are you doing that others missed, and what special cases still need to be handled.
If you are a team:
- Create a thread on the forum where you can discuss things with your teammates.
- Create a Scenario Plan where all your team members are marked as trusted. This will allow you to test each others' contributions.
- Once you are satisfied with your work, have every member of the team (and anyone else you can convince) rate all of the Rules you created to make Elody trust them.
You are heavily encouraged to name your objects according to the following scheme, to make things easier to understand for other developers.
Symbols are named with underscores and start with a lowercase letter: this_is_a_Symbol
Before adding a new symbol, check if something similar already exists. Symbols with duplicate meaning create extra work for contributors!
When choosing names for new symbols, be very specific. Different people come from different backgrounds and use different Programming languages so they can have very different standards.
The following prefixes are common:
These Tags are supposed to be used to trigger a Demo- Rule directly and have no meaning beyond that.
Represents a type of task. Should be used in conjunction with !task.
These tags always target a task_ tag as their first argument
The prefix 'require_' here is actually more than just a convention: Elody considers a task_ to be finished if all the require_ tags on it are tagged with !provide.
Used by a Rule to temporarily reserve an object.
The kinds of Tags are used to describe the format of a file. The first argument of such a Tag should always be a file.
You can combine this with the prefix require_ to form a 'require_format_' Symbol, which indicates that a file needs to be in a certain format.
Programs are named with underscores and start with a capital letter: This-is-a-Program
Alternatively, they can also be written with capitalized camelcase: ThisIsAProgram
Rules are named with hyphens and start with a capital letter: This-is-a-Rule
Options are named with hyphens and start with a lowercase letter: this-is-an-Option
It is recommended to name Options similarly to the Rules that created them, whenever doing so makes sense. Often it is even the most understandable if you give the Option the same name as the Rule, just without the capitalized first letter.
Variables in Rules and Options
Rules and Options can contain named variables. Use camelCase with a lowercase first letter for them: thisIsAVariable
Prefixes for Rules and Options
Most Rules and Options can be roughly categorized by the purpose they serve. If a Rule or Option matches one of these archetypes, it is a good idea to give its name the corresponding prefix. This will make it easier to understand for other users:
These Rules are supposed to be triggered directly through a corresponding demo_ Symbol. They should not be called in an ordinary Scenario and should only be used when explicitly triggered at the start of a Scenario.
The Rule or Option is used as an intermediary to spawn another Option that does the actual work. Since all Rules are supposed to work like this, using this prefix this is not necessary for Rules. It can be useful for nested Options, though: give the higher level Options a 'spawn-' prefix to make it clear that it acts indirectly by creating another Option.
The purpose of this Rule or Option is to interact with the user.
This Rule or Option waits for a particular condition that may or may not occur and reacts if it recognizes the condition.
A prefix for Options that should be presented to the user so that the user can manually verify something. Similar to 'Interact-'.
A helper that lays the groundwork to make another Rule/Program possible, usually by triggering an Enrich- Rule that is needed to get it to run.
Enriches a Scenario by populating it with additional objects that may be needed.
Generic prefix for when nothing else applies.
Presents information to the user. Often the last step of a task.
This is used when fixing someone else's Rule the hard way. It is not cooperative, and not recommended if an alternative exists. If you have to do this, make sure to contact the author of the Rule you are fixing and tell them about it, so that they can fix it themselves and the Hotfix- Rule can be deleted. The Options generated by a Hotfix- Rule get the prefixes 'undo-' and 'hotfix-' for undoing the mistakes of the orginal and for making things right, respectively.
Used for Options that are supposed to run immediately after another event is finished, most often a Program execution event.
Used for Options that perform clean up operations once some conditions are met.
Symbols have meaning. Try to make that meaning clear in the description.
If it is not clear what your Symbol is supposed to represent, other developers may misuse it and that could make both your Rules and theirs less effective.
While you are able to change the description of a Symbol later on, this is intended for small changes. Don't change the way Symbols are meant to be used when those symbols are already in use by other developers.
It's better to have too many Tags than too few.
Tags can be used to describe things, to connect things, to activate or suppress Rules, and for virtually any imaginable other task. Try to express as much information as possible with Tags. You never know when something you consider unimportant might be useful for another developer.
To make it easier for Rules to cooperate with each other, explicitly define tasks with requirements whenever doing so makes sense.
To define a task, use the !task Symbol as well as another Symbol beginning with 'task_' that describes what the task is about.
The purpose of a task is to make sure that Rules and Options can be used multiple times in the same scenario and don't get confused about the objects they should use as arguments.
Tasks can be independent of each other, or form a directed acyclic graph. Presumably most users will only have one concrete task and start a new Scenario for the next task, but you never know when someone might upload code that builds on your tasks to solve a more complex task.
Every time the user wants to do something new that is independent of what he wanted earlier, create a new task object.
Every time a task requires multiple subtasks of the same kind, create a new task for each of them.
If a task has subtasks, but only one of each kind, then there is no risk of confusion. In this case, explicitly creating a subtask is Optional. This is the case in the example, where require_ and !provide are used for each of the subtasks, but no subtasks are created explicitly.
Rules and Options
Use Options as intermediaries
You can always choose between having your Rules do things directly, or creating Options as intermediates. If you go the first route, then the consequences of your Rule can't be interrupted or suppressed once it has been selected for execution. This may seem like a good thing at first, but it isn't.
If your Rule ever does something bad, and nothing can interrupt it, then it will receive negative feedback. Eventually, Elody may decide not to use your Rule anymore because it causes problems too often, even if it is normally useful.
On the other hand, if your Rule acts indirectly by creating an Option, then other Rules can suppress or interrupt it when necessary. As a result, your Rule will still be used when it does something useful, but it will be suppressed when it would do something harmful.
Rules should be independent entities.
If another Rule that your Rule relies on has a too low rating to run, make sure that your Rule does not do anything stupid. If possible, make it fail gracefully and maybe create a Message (visible only to developers) in which it mentions that another required Rule did not get loaded by Elody.
If it is not possible to do this at all, consider merging both Rules into one.
When you set the confidence of an Option, follow these guidelines:
- <0.5: Probably wrong. Only display these Options if nothing else works. (0.5 is the default threshold for ignoring an Option vs. displaying it to the user.)
- 0.5-1.0: Probably good, but better to ask the user first. (1.0 is the default threshold for displaying an Option to the user vs. executing it immediately.)
- 1.0-2.0: Most likely useful. Execute this Option without asking first, unless the user has high security standards. (2.0 is the maximum threshold value for displaying vs executing that a user can select)
- 2-999: These Options should always be executed, but the ones with higher confidence execute first. Choose the confidence based on what confidence values other Rules use.
- 1000: The confidence here is a formality. The only important question is whether or not the trigger matches, and the code here is only put in an Option to give other Rules a chance to !deactivate them. These Options should otherwise always execute. Most Options generated directly by Rules get this confidence.
- 9999: postprocessing- and cleanup- Options. Their confidence is extremely high to ensure they run without delay once their trigger's condition is met.
If two Rules are direct competitors with each other but cooperative, they should give the Options they create the same confidence. If two Options have the same confidence, the one that was created first takes precedence. Since the order in which the Options are created depends on the order in which the Rules were executed, this ensures that that the Option from the Rule with the better rating takes precedence.
If one of the Rules is not cooperative (i.e. it creates its Options at a higher confidence than the others), then the way to deal with this is to forcibly deactivate the non-cooperative Rule as demonstrated in the tutorial.
This website is currently in Beta. If you think you know a better way to do things, please tell us about it!
Rules and Options that are meant to execute only once should always call deactivate_self
This explicitly removes them from being listed in Elody's Decision Process, which makes things easier to follow for other Programmers by making the Decision Process less cluttered with irrelevant information.
Rules and Options should clean up after themselves
If there is a chance that an Option won't be executed, make sure it gets deactivated by a cleanup- Option, so it doesn't clog up the Decision Process log.
Be careful about your runtime.
It costs some time to start a Program, because each Program runs in an isolated environment for security purposes. It is therefore faster to solve multiple problems with a single call to a Program than to call the same Program multiple times with different parameters. On the other hand, solving many different kinds of problems with the same Program can get quite confusing. Be mindful of both issues and try to find a good balance.
This website is still under development. The speed of executing a Program and the overhead of starting a new Program may be improved as the technology matures.
There are some guidelines to consider when rating a Rule or Program, or when creating feedback request forms so that other people can rate them.
Don't lie about responsibility.
It is possible to create Feedback Request forms for Rules and Programs that aren't yours. This is a deliberate feature since it can somestimes be useful. Do not abuse it to make misleading feedback requests. This is grounds for the deletion of a Rule or Program even if it otherwise works very well.