A manager describes the need in one sentence: "I want an application like my supplier's". Three questions later, it turns out what actually costs him time is retyping every delivery note into a spreadsheet each evening, and never knowing what is left in stock without walking to the warehouse. The application he described would have solved nothing. The one he needs did not appear in his sentence.

The problem before the solution

A client almost always states a solution, rarely a problem. That is natural: they have already thought about it, and they present the result of their thinking.

The work consists in going back. What happens today, concretely? Who does what, when, with which tool? Where is information entered twice? What produces errors? What stops them answering a customer straight away?

Out of those answers comes an understanding of the real need, which does not always resemble the original request. A developer who starts by choosing a framework before doing that work builds the wrong thing correctly.

Turning an idea into a testable scope

A useful scope is not a wish list: it is a series of statements you can check at the end.

"Manage stock" is not testable. "Record an incoming delivery with its quantity and supplier", "show available stock per item", "alert when an item falls below a defined threshold" are. Each of those can be demonstrated, accepted or rejected.

The scope also sets out the users and their rights, the data, the integrations, what the client provides, the timescales, the deliverables — and what is explicitly excluded. A project rarely goes wrong on what was written; it goes wrong on what each side thought was obvious.

Deliver in stages rather than at the end

A project the client sees nothing of before the end rarely finishes well. Not through bad faith, but because an application is understood by using it, and nobody can describe in advance something they have never handled.

Delivering a usable version at regular intervals changes the nature of the project: the client corrects course early, when a design mistake costs a conversation rather than three weeks of rework. That means cutting the work by unit of usefulness — a complete, usable function — rather than by technical layer.

The durations announced are a matter of the provider's organisation and the project's complexity; they follow from no standard and vary too much for a general figure to mean anything.

Data is the skeleton

What you see of an application is screens. What makes it last is how the data is organised.

Deciding what constitutes an item, a customer, an order, an order line, and how those objects relate, is a structuring decision that is not easily undone. Poor modelling does not show at the start: it appears the day you want to add a function the structure forbids.

Very concrete things are settled here too: which information is mandatory, which may stay empty, what must be unique, what is genuinely deleted and what is merely marked inactive. Data erased by mistake in a badly designed application does not come back.

Choosing tools somebody else can pick up

Technical choice is often presented as a matter of preference. It should be a matter of lifespan.

The right question is not "what is the most modern tool" but "who will be able to take this project over in three years". That points towards widely used, well-documented technologies, with a community and developers available locally — rather than an exotic choice the client would become captive to.

No-code and low-code tools follow the same reasoning: they save real time on some needs and are paid for elsewhere — functional limits, subscription cost, dependence on a platform, uncertain export. Neither superior nor inferior in principle: they suit, or do not suit, a given need over a given horizon.

Testing: what has to keep working

A test is not there to prove the code works on delivery day. It is there to make sure a future change will not break what already worked.

Critical functions — those whose failure costs money or trust — deserve automated tests: calculating a total, recording an order, authentication, permissions. The rest is tested manually against a written scenario.

To that is added acceptance testing with the client, which tests something else entirely: they check that the application does what was agreed, in their real conditions, with their real data.

Application security from the first line

An application reachable from the Internet is permanently exposed, and most common attacks are automated.

The most widespread defensive reference is the OWASP Top 10, published by the OWASP Foundation: an awareness document for developers and web application security teams, setting out the most critical risk categories for web applications and presenting itself as a first step towards more secure development.

In practice it comes down to writing habits: never trust incoming data, check authorisation on every action and not only on display, keep no secret in the source code, keep the libraries used up to date, log what needs logging, and provide for database backups. A developer who delivers without saying how the application will be updated leaves behind a debt that grows on its own.

Interfaces, accessibility and proof

An interface is judged in use: what the user sees first, what they understand without explanation, how many actions a common task costs them, and what happens when they make a mistake. An error message that says what to do is worth more than a technical code.

Accessibility is part of the same work. The Web Content Accessibility Guidelines, published by the World Wide Web Consortium through its Web Accessibility Initiative, have the status of a W3C Recommendation. They are organised around four principles — perceivable, operable, understandable, robust — and define three conformance levels, A, AA and AAA. They are not binding by themselves: they become so where national legislation adopts them, which some countries do and others do not.

Where an application records a commitment — confirming an order, accepting terms, signing a document — the question of proof arises. The UNCITRAL Model Law on Electronic Signatures, adopted on 5 July 2001, offers States a framework built on functional equivalence, which lets an electronic signature satisfy a legal signature requirement where it offers the required guarantees, and on technological neutrality. A model law is not a treaty: it holds only where a State has enacted it, and the concrete requirements are found in national law. On the developer's side, what belongs to the trade is keeping records that are dated, consistent and not alterable after the fact.

Taking over someone else's code

A significant share of the work consists in picking up an abandoned project. That is a different engagement from new development, and it starts with an honest audit.

That audit answers three questions: what actually works, what is salvageable, and what would cost more to repair than to rewrite. The answer sometimes displeases. Giving it anyway is what separates a professional from someone who takes the project on and discovers the problem once paid.

The audit also looks at what is not code: does the access exist, is the database backed up, are the domain name and hosting in the client's name, is there any documentation, and did the previous provider hand everything over.

Delivery, access, documentation

Delivering is not putting something online. It is handing over what is needed to continue without you.

That includes the source code and its history, access to the environments, the technical accounts and their rights, the deployment procedure, the state of the backups and how to restore them, short documentation, and training on the administration functions.

Credentials are handed over methodically: named accounts rather than a shared one, rights limited to what is necessary, stronger authentication where it exists, and the provider's access revoked at the end of the engagement. A password sent in a group chat or stored in an unprotected file cannot be taken back.

When artificial intelligence writes code

AI assistance is part of many developers' daily work, and it saves real time on what is repetitive: function skeletons, tests, conversions, documentation, explaining unfamiliar code.

It calls for a precise discipline, because "it works" is not a sufficient criterion. Code can produce the right result while being fragile, inefficient, insecure or impossible to maintain. Generated code is read, understood, tested and integrated like any other — responsibility for what is delivered remains entirely the developer's.

Two further precautions apply. Confidentiality first: client code, real data or credentials are not pasted into a tool without knowing what it does with them. Rights second: what is produced may draw on sources whose licence matters, and a professional makes sure of what they are entitled to deliver.

In African contexts

Working conditions vary sharply from one country and one city to another, and there is no single African context. Several constraints nonetheless recur in some contexts and deserve to be designed for rather than endured.

Where the connection is irregular or billed by volume, an application that demands a permanent connection becomes unusable half the time. Designing degraded operation — offline entry, deferred synchronisation, lighter exchanges — is then not a comfort option. Where the phone is the main working device, the interface is designed for the small screen first. Where mobile money is the ordinary means of payment, integrating it governs whether the application is actually used, and the available solutions differ from country to country.

On data, the applicable framework depends on the country. The African Union Data Policy Framework, published on 28 July 2022, aims to strengthen and harmonise data governance across the continent in order to create a shared data space serving an inclusive digital economy. It is guidance, not binding legislation: what actually applies to a given application flows from national law, including any rules on data localisation or transfer.

Finally, the availability of developers varies greatly between cities. That is a further argument for choosing widespread technologies: a client should never depend on one single person to evolve their working tool.

What a developer does not promise

A developer does not guarantee the absence of defects, nor that an application will never need to change, nor that a third-party service will stay available and free, nor that a deadline will hold whatever the circumstances. They depend on hosts, programming interfaces, libraries and operators: they cannot commit to total availability of a chain they do not control.

What they do commit to can be checked: a need understood and reframed, a testable scope, regular deliveries, tests on the critical functions, documented code handed over, access transmitted, a backed-up database and an application the client can have somebody else take over.

That is also what makes the activity credible: a professional name, stable contact details, completed work presented as it is, a quotation itemising each feature, a contract saying who owns the code, invoices, and follow-up on requests after delivery.

Finally, this article describes a trade; it replaces neither a brief nor legal advice. The rules mentioned vary from country to country.