Formal Yet Simple Development

The FYSD method brings together a flexible set of software development principles and processes designed to efficiently frame software organic evolution while preserving it from product delivery management constraints.

Definition:

Software applications can be part of a business delivery and therefore might share some initial considerations with, but they do have their own requirements and impacts, their own paradigms and perspectives.

Ensuring the integrity of these aspects involves a complete separation between the product management and the underlying software components life cycles.

Definition:

  • project - software application, single software component of a product

Such a separation is most likely achieved by splitting business logic across various projects labelled using codenames and independently managed through distinct processes by the technical team members, allowing this way technical governance to remain a technical responsibility. In other words, project management by developers for developers whatever the product directions in place.

One or more team members would then have to take part in the product management processes in order to be able to translate the different product milestones into project specifications, and report back the corresponding progress.

Definitions:

  • internal management - self-contained project-specific management processes
  • interfacing - back and forth adjustments between product and projects managements

Both layers of processes might at any time introduce new elements virtually altering a project while in fact resulting in a different project, namely:

  • incompatible specification update (including breaking changes)
  • significant business logic additions
  • tech stack migration (large code rewrite in general)

A typical and effective answer would then be to proceed with an internal fork of the project, eventually deprecating the former.

This separation is equally relevant in open-source development, for many popular projects truly are managed as corporate products. Smaller scale projects however simply do not carry any notion of "product" - as there is often no business vision besides answering users needs - and <together with|taken into account|knowing|given> their decentralized contribution model, <it's making them> easy and ideal to to be conducted through self-contained processes.

General project coordination

<1:software/agile critics>

Depending on the project per team <size and proportions|segmentation>, it's up to the team itself to define a synchronization structure, stating whether meetings should occur to cover each project individually, divided into <fitting|relevant> scopes, or as a whole.

Definitions:

  • scope - topic for a team synchronization step, covering one or more projects
  • coordinator - team member in charge of formalising scope actions

Following this structure, keeping track of meeting outcomes - or any other form of project update - becomes as easy as maintaining a single <central|authoritative> document for each scope. A simple and flexible medium for project management logs and reference.

Its form can be declined according to various integration needs:

  • plain text file: the KISS way, independant from editing and network tools, system tools friendly
  • online boards and planning platforms: the corporate way also works
  • office document: cloud-hosted or local, but versatile interface
  • any corresponding [template][6.5] can be applied on top

[6.5]:

This approach is not meant to depict project directions nor progress status, actions should immediatly be transposed to appropriate project-specific documents. It however fits any project governance and transparency model:

  • fully collaborative: any team member can ammend the document at any time
  • assigned coordinator: each scope its own coordinator, holding control over the document
  • reserved coordination: document is not shared, other team members can focus exclusively on scope project(s)
  • rotating coordination: a new member is picked to coordinate the next session(s), maybe on a time period basis
  • dedicated coordinator: a single member for every scopes
  • any combination of the above

Meetings might take place regularly, always involve the whole team, and have the coordinator to share his screen while editing the scope logs live, but it might as well be <more suitable|better advised> to favor slower pace decision making and limited <> overhead <and [interruption][]>:

  • asynchronous communication: copying a coordinator into an email, enforcing documentation processes, group chats, filling a bug report ticket
  • voluntary participation: allowing team members to skip unnecessary meetings by including and gradually filling up the "order of the day" in the document

Face-to-face is otherwise most <beneficial|useful|best suited> for pair programming,

<naturally|typically> <for|part of> routine feature development, but even better

newcomer onboarding and code review sessions.

Project task management

A project roadmap provides the big picture of its progress and a great main gateway to its internals. It is better represented as a self-contained document, here again ideally KISS-like as a text file, but <> While it should indeed incorporate and be authoritative upon the description of the software component requirements, the whole specification might spread out over any number of additional documents such as test cases, RFCs, or domain-specific interface definition files. This roadmap file is mostly meant to be read by developers, to be used as a translation layer for product management interfacing, and might as well be maintained by the project's scope coordinator.

Any technically relevant structure might be used to categorise tasks but what all software is about can be strip down to:

  • input data and options to support
  • output options to support
  • respective operations to make available
  • debug and user-facing data report options

Tasks would gradually and continuously be added all along the project duration: as the coordinator brings in business requirements, and following a predefined set of splitting rules. Whether or not high level tasks are unclear or approximate when formalised by the coordinator into the document, further narrowing and refinement would naturally come out of splits. Some task would directly flow from the roadmap categorisation: output and report related tasks might for instance result into test case definitions and implementations. Splitting should be destructive but hierarchy and dependancy relations between tasks can be preserved using metadata - commonly via tag system. A task fitting within a single development session is considered resonably bounded, and to be better divided if still ongoing once the first session is over. It should otherwise remain a splitting candidate. In a decentralized workflow, team members should self-assign on upcoming tasks, and all subtask should be added unassigned.

The team is encouraged to enrich tasks with extra technically relevant annotations, considering priority and estimation metrics are mostly interfacing-specific which can only be inaccurately built based on previous progress feedback from the coordinator. Roadmap tasks should exclusively answer to scope log action updates - derive from established scope requirements.

Project life cycle

The FYSD method runs through project development iterations <following|according to> different software maturity , blending flavors of TDD and formal conventions as a progressive take on strictness:

specified enough to be brainless.

Code migration or rewrite from and to different languages or tech stack, resulting or not in project forking, is advisable whenever appropriate, and might happen at any stage of the project. Any new project might therefore start at arbitrary point of its life cycle.

1 - Dogfood stage

Prototyping period of the software component, exploring and designing approaches to validate initial requirements.

At this point, the roadmap file should mostly contain minimal specifications. Assumptions should be made towards its composition aspects: environment-based parameters and configuration, use of standard IO streams and presuposed working directory.

The whole implementation should be written as naive code, without any language nor third party dependancy restrictions, and within as few files and sections as possible. However, test cases should match and enforce output and report expectations, and basic free form comments should complement any code - TODOs, explainations, branstorming ideas.

Basic versionning should be setup on a single branch, following a patch-based workflow with minimal why commit message. The project name and brief description should appear from the repository's README.

2 - Frozen stage

A strengthening period to introduce long lasting code architecture and future-proof practices.

The roadmap should now include exhaustive error covering and eventual options for advanced configuration. Error cases should be updated accordingly and each test case might now be subdivided in typical scenarios when appropriate: failure, fallback, lazy acquisition, and success. Feature demonstration should be generated from relevant tests' markdown comments (comming soon).

FYSD design patterns (comming soon) should be taken into account for all corresponding and later code implementations, and the team can now start to consider internalizing dependancies as part of the current project or as a separate new project. In any way, left dependancies' licenses should be mentioned from the project repository in addition to its own (comming soon). Build instructions, if relevant, and file structure presentation should be generated from the build process itself: a dedicated first verbose level, then incremental debug informations when specified. The README should snapshot a dump of these instructions, and might also provide a visual preview of the software such as screen or terminal captures, or even slides.

The team should agree on naming one or more reviewer for the project and for any new patch set to be peer-reviewed. Furthermore, generated files - single-target, including debug code and/or data - might be distributed alongside the repository.

3 - Evaluation stage (beta)

Openning period, preparing for wider use while seeking for feedback.

Most issues during early stages are self-reported by the team, but as more bugs are filled in, and as the roadmap may now accept alterations to the original requirements - as current use-cases are getting better defined, repetitive ones identified, unanticipated ones discovered -, cheat-sheets, user narratives, bug reproductions should all be documented as test cases.

Essential implementation, commenting and testing practices from previous stages should naturally carry on, and to promote ready-to-use code, modular and reusable code sections should provide extensive documentation (comming soon) as markdown comments (comming soon).

Since any project exposition might introduce an increased diversity of topics at a faster pace, additional steps might be necessary to prevent reviews to be rushed, reviewers to favor some aspects over others. A common way might be to multiply reviewers for every single patch-set, but more effective and decentralized options include upfront steps such as RFC writing, or multi-step reviews (comming soon) to ensure every concern is covered.

Nevertheless, contribution instructions should be accessible from the project README, along with updated visuals, licenses, and build instructions. Development overhead can be reduced by automating such updates and other artifact generation and distribution through pipelines, asuming their maintainance remains simple.

4 - Expansion stage

In line with already ongoing integration processes of requirement updates, but appart from hobby or educational projects purposes, a stage to make the project aware of its domain's state of the art, to harvest developer approbation and user adoption.

With accumulated complexity, guiding material, overall organization needs, and exactly as initiated in preceding stages, reference links to all ressources and documents should be accessible from the project README: the project repository entry point and thus primary source of trust.

All previously documented code along with the whole source code itself shall be extracted and generated as distribution artifacts through their respective pipelines for conveniance and compliance to free software guidelines.

Including nice-to-have features and eventual bindings - or any other external interface layer - to the roadmap when relevant are just as many

<great|useful> ways to challenge the project design while improving usage experience and satisfaction. It might end up resulting in a project fork, or being implemented on its own separate project, but anyhow, feature parity check should be automated as test case to lower maintainance efforts. The team should consider automating benchmark as test cases as well to guarantee the software performance trend and ressources usage control.

Various components such as badges and statistics samples can be added to the README to boost the project visibility and lower its entry barrier. A comparison matrix document featuring well known equivalent software is a cheap and visual option to consider. It is further possible to annex migration guides from those alternatives. To go even further, writing the guides as scripts with markdown comments, and to the greatest extent, implementing those scripts as test cases.

5 - Maintenance stage (stable)

Stability and support improvment period.

The major part of development efforts are here concentrated on fueling and preserving the project momentum.

It's however welcome to introduce late-game requirements: usually regarding [optimisation][14.1], and extending range of target and binding support.

It might also be relevant to explore advanced testing strategies, for examples fuzz testing for failsafe guarantees, or opt-in A-B testing for experimental features.

[14.1]: #premature optimisations#


  • debt scripts??