=head1 Complete Programming
This document describes the method the Kephra editor is developed with.
Its highest aim is to have at all times a usable program with the
highest quality at all levels while still allowing programming be fun.
The name is a reminder that we reach for the impossible,
because software is never complete. So please focus, enjoy and relax.
I strongly dislike strict rules imposed on me and make fun of people that produce
theories with three letter acronyms that try to be the answer to everything.
But now I am standing here, trying to "sell" you yet another programming methodology.
That IS irony, isn't it?
At least I have just a two letters acronym to sound even more important.
=head3 Basic Ideas
Well, several reasons brought me here.
1) I always wanted a sane balance between the old bureaucratic waterfall method,
and the modern extreme or agile programming, which is a bit too shortsighted
and accumulates additional work as the project grows.
It should be possible to combine sound planning, practicability and quick results.
2) All methodologies I know of overlook several aspects of the product.
That includes even "documentation driven development",
which gave important impulses for the creation of CP.
3) Documentation coverage and depth matters a great deal and writing it also
helps the developer.
4) The awesome powers of prototypes are known but still not fully used.
5) Writing tests is no silver bullet. It is used for several competing purposes
and in an unnatural way. That's why a lot of programer hate it.
6) New tools like hg or git allow new workflows which solve pending problems.
=head3 Main Goal
Highest aim of CP is the conscience the code is produced with. As result you get
=item a superb overall user experience
=item quality code
=item transparent project planning and status
=item room for experiments and changes without trouble
=item Every action has a productive and lasting (yet changable) result.
=item Honest and brief communication is key.
=item All code, data and metadata form one project and go into one repository.
=item They are all equally important.
=item Don't plan new feature, document it from users point.
=item just annotate technical requirements.
=item these low level functionalities are testet first in a prototype.
=item Than follows a usability prototype.
=item When implementing a feature, envision and do all aspects at once.
=item Only after something went into the main programm a test is needed.
=item We rely heavily on branches and decentral version control systems.
Lets start with a small meditation, because Complete Programming (CP) relies on
embodying a mindset that is still a bit alien to some. In one word it is holistic -
meaning seeing the full (complete) picture. That includes the views of the user,
the programmer, the designer, tester and project manager.
That sounds demanding, but you do it already when you really care about something.
As a consequence we count an ugly icon, missing documentation or an badly
designed internal API equally as a bug as a crashing function. CP is designed
to deliver that high standard, without packing too much burden on the programmer.
Firstly: all aspects of a feature are planned at once - so they're in tune with
each other. And they are also imlepement together - when details are fresh in
your memory. And since that also includes comments and documentation, you will
later know what you have done and why, saving a lot of guesswork.
Secondly: we reduce duplicate work and duplicate data where possible. CP will
compel you to think about a problem several times, to ensure you unerstood its
implications. But every time you will produce a useful part of the project.
Every vital information goes into one well structured repository (again holistic!).
Your highten clarity and low duplication also improves the quality of communication,
that will mainly take place through your common work (repository).
And thirdly: as hinted, the development model knows several decoupled, well
defined stages that correlate with the natural flow of ideas into materialisation.
Any stage has only one goal that is set according to its possibilities and with
respect to its unavoidable limits. That's one reason why work gets less heavy.
(Joyful labour is important to get the deeper focus we need to achieve quality.)
The other reason: some stages allow free minded hacking and bring back the fun
you missed for so long. (Play and work balanced - that is holistic too).
The next chapter describe each stage in detail.
As said here is not much planning involved because of reasons already stated.
Nontheless there are severel things to be decided at start.
* general vision of the program with use cases
* on which technology to rely (with fallback alternatives)
* what team we need (especially in corporate setting)
* small roadmap
Write that down (except point 3) by the rules given in the next chapter.
In CP that is already considered coding since you write documentation.
The development cycles have already began. So please don't overdo it,
since everything can be overwritten when other information become available.
You might protest that your boss (that needs to read the summary of that newly
proposed undertaking) requires a different style or format. But you both work
on the same project and have to form a complete whole. Documentation should
be written so clear that even business people can understand it and the manager
can make much better decisions when he knows what you actually do.
Duplication leads to unproductive work and enbles miscommunication.
Managers usually understand such arguments.
One last, but very important thing during that phase - adapt complete programming.
First you might commit this text as part of the developers documentation,
that should reflect briefly all the processes involved. Than you alter details,
because your program maybe has no GUI, or config, or you will need more branches.
Maybe want to tweak the role of tests - by all means these are not the ten
commandments. And please give us a feedback when your tweaks seem to work well.
As you saw, we start always by writing documentation, forwhy its usually better
to think before doing anything. And putting it down helps you reflect on it.
Knowing that it will be read by programmer or users should add pressure,
or let's say serious focus. But please don't overdo it. Just stick to things
you're sure about and are plannable right now and be sketchy with the rest.
Then start crafting placeholder code or prototypes that reflect what you just wrote.
If you think it through - the first thoughts are too vague to build a good program.
Either you do for a while try and error to find a good structure and the right
details, or you start with defining what you want to achieve. This way you get
the docs right away while doing the necessary thinking and you don't have to write
them later. Even better - programming will become more streamlined too, because
you don't have to think about where you going and how to implement it at once.
And as you will see, we will break up that process into several more steps,
before coding the final product.
Some devs feel writing docs is unproductive, a waste of time or should be done
by people more talented to do that. Even if good UI design is "self-explanatory",
missing docs are crippling the usability and not findable features are not
distinguishable from not existing ones. Thatswhy only documented features, libs
and API's are quality work. And since you wrote them, you should document them.
It would take more time to explain it anyway, especially to a none-techie. And
switching to the users perspective - that is what you need to do for good docs -
you also need to develope good software.
The reason why docs are considered in the "agile" field as less important,
(agile manifesto says: "Working software over comprehensive documentation")
because they confuse it with overhead. In CP we don't document planned features,
just note them in a roadmap. And managers will get high level user docs.
That means we have almost no overhead and the docs have to be so good,
that even mangers an understand them. For managers its also helpful to
understand the language of the user and to know what is actually been done.
Since the boss will get no special report, it gets harder to cheat or fall into
other traps of miscommunication, that is enabled by duplication of information.
Meetings get more productive too, when arguing has a common knowledge base and
results will become directly part of the product.
User docs, developer docs and comments, as well as the code itslef are means of
communication between people. They have to cooperate. All these parts should have
a common language and define key words and phrases in the exactly same way.
Less friction here is an enormous productivity boost - a further reason,
why they gotta be written altogether and by the same people.
Nevertheless things not always turn out as planned. So quite often the docs have
to be adjusted after the implementation of a feature. That oughta be done anyway,
as first phase docs were just sketchy drafts, stating what you could know then,
which becomes more after the coding. Small iterations between these states amplify
an holistic understanding and overall quality. The exact rules how to iterate
are part of the chapter L<Itersations>.
One of the things Steve Jobs got right was: "Start with envisioning the user
experience and then work your way through the technicalities.". CP does that by
beginning with a bit of user documentation - followed by an explorative phase,
where developers find out how to realize it by writing prototypes.
These are small, quickly written programs that are test beds for very few things.
Usually do programer enjoy building them, because they demand less restrictions
than huge programs and allow much more fast changes and creativity.
This way ideas get stable without harming the "real code" and coder have more fun.
And if a prototype turns out to be a blind alley, it can be deleted without remorse.
Some may now intervene: "Why not just fork an experimental branch, if we using hg,
git or arch anyway? Afterwards it can be just merged back by the software and we
don't have to write that code again in the main program.". Well, like said dealing
with a huge program is much more hairy and distracts you from the detail you want
to get right. You get way faster done with a clean start prototypes provide.
And beside that - the code that will flow back is not as much compared with the
many trials and errors that might pollute the history of the main project branch
if you merge it there. There is still rebase, that cleans it up, but you might
preserve that history in the right place, since there you learned your lessons.
Prototypes also serve an educational purpose. Programer often look up how they
did something in their own programs. That is much easier with nicely commented,
sorted and indexed prototypes that sit and wait unchanged in their own branch -
presenting just the essence how to solve one particular problem. Its a kind of
documentation from programmer for programer. But this works only if a solution
is also tidied up after its found. When you later want to test another idea just
clone or copy a similar prototype and you already got the needed minimal framework
supporting that kind of function.
All that would be much harder if you just fork a fast changing main program.
A completed prototype has also a role similar to a test. It demonstrates that a
chunk of code works that way. You can't practically achieve that while have having
a lot dependencies that can introduce a failure into an otherwise working piece
of code. And even beside that - in CP we have a way to write prototypes,
where you can do heart transplant to the production stream without greater trouble.
CP knows two types of prototypes that are living in two seperate branches.
That's because the main program has to bridge two endpoints which are too different
to think about and optimize for at once. That are the hardware or the near
hardware software layer and the user. For the one side we have functional
prototypes and for the second use case prototypes.
=head4 Functional Prototypes
After starting with a users wish, we go to the opposite end of the spectrum,
to the building blocks of a program like computing a formula or writing a file.
Because it doesn't make sense to plan on details if we don't know if it can be
built or how. I mean experienced programmer know a lot, but there are far too
many fast changing libraries, techniques and domains to know it all. And docs
can be unclear, missing, lying or simply out of date. So only when you built it
and it's running you can be sure it runs. Therefor we do functional prototypes (FP).
A FP has only one file and should be as short as possible. It can be used to
check out how third party libraries work, but none of the projects libs should
be used if possible. FP need no exceptions, no logging and alike.
Just solve a core problem that is needed to implement a feature.
If there are two ways to implement, try both. Usually that's not much more work
and you can later make wiser decisions. Especially in discussion with the lead
programmer that knows the whole structure and maybe sees more implications of
these alternatives. That became only possible, because well commented FP are
easier to grok than main program code.
=head4 Use Case Prototypes
=head3 Main Program
* documentation (user, programmer, comments)
* logic (main program)
* supply libs
Third Step: Imagine some rought logical structures the program is built upon.
Use UML only if you have to, better are empty classes / packages / module with
almost empty meths / subroutines. Inserts comments that say what goes where.
Coprogrammer will understand you far better, you spot practical design flaws
much faster and you will feel better, because you did already something productive.
write after code
and its stable
have to change them less
its after thought
test first doesnt work with gui
put into code just seperate starter
BETTER TESTING — WORSE QUALITY?
see more in L<lib/Kephra/Versioning.pod>
parts to do