Skip to content
Léo.
All projects
Software engineeringCompleted2025 – 2026

EasySave

A .NET backup tool delivered across three releases, from console app to real-time dashboard.

CESI · Software engineering · Team project

Illustration: backup dashboard
Illustration: backup dashboard
Client
ProSoft, the fictional client of the brief
Team
3 developers
Releases
v1 console → v2 WPF → v3 parallel
Target
Windows 10/11, .NET 10

Key points

  • Three successive releases on a single codebase
  • All jobs run in parallel, with per-job play / pause / stop
  • Cross-job rules: priority files, one large file at a time
  • JSON or XML logging, locally and to a Docker service

The walkthrough

Walkthrough: three jobs running in parallel, one paused, resumed, and the operation log.

How it works

  1. 1

    Define a job

    A backup job is three pieces of information: a source folder, a target folder, and a type, full or differential. The job list lives in a configuration file, along with the extensions to encrypt, those declared as priority, the size threshold above which a file counts as large, and the name of the business software to watch for.

  2. 2

    Scan and compare

    The whole source tree is walked. In a full backup everything is kept; in a differential one, each file is compared with its counterpart in the target and kept only if it changed. The two behaviours are interchangeable strategies behind one interface, which is what makes adding a mode possible without touching the engine.

  3. 3

    Copy

    Selected files are copied one by one, and this is where the rules apply: an ordinary file waits until no priority file is queued anywhere across all jobs; a large file waits its turn so the network is not saturated. Each job's progress reaches the interface during the copy, not at the end.

  4. 4

    Encrypt

    Files whose extension appears in the configuration are handed to CryptoSoft, a separate executable applying XOR encryption. Only one instance may run at a time on the machine, a requirement of the brief, enforced by a named lock at system level rather than process level.

  5. 5

    Log

    Every processed file produces a log line: timestamp, source and target paths, size, transfer time, encryption time. The log is written as JSON or XML, locally, to a containerised collection service, or both. A separate state file continuously describes what each job is doing, making execution observable from outside.

What the software does

EasySave backs up folders, on demand or before a risky operation. The user declares jobs, launches them from a dashboard, and follows their progress file by file. Some extensions get encrypted along the way, everything is logged, and the software pauses itself if the company's business application starts, because a backup has no business slowing someone down.

The module's constraint

The brief imposed a constraint more interesting than the product: deliver three successive versions for a fictional client, ProSoft, evolving the architecture at each iteration without rewriting from scratch. Each version came with its own requirements, revealed only once the previous one had shipped, so designing everything upfront was not an option.

The three releases

What changes from one release to the next is not the amount of features but where the code lives.

  • v1, console, the engine: folder walking, full or differential backup, per-extension encryption, daily log, state file, French and English interface. Five jobs maximum, run one after another.
  • v2, graphical interface, the engine is extracted into a library shared by the console and the new WPF window, built in MVVM. The view no longer knows the logic, logging becomes a separate component with JSON or XML, and the job limit disappears.
  • v3, dashboard, every job runs at once, each controllable individually or all together, with the rules that become necessary as soon as things stop running in single file. Logs can be sent to a containerised service.

How it is split up

The solution holds seven projects, and that split is the module's real deliverable: it is what absorbed three successive sets of requirements.

  • Core, models, services, backup strategies and ViewModels: everything that depends on no interface
  • Console and WPF, two front ends on the same engine, the second added without touching the first
  • EasyLog, logging kept separate, with one strategy per output format
  • CryptoSoft, standalone encryption executable, called as an external tool
  • LogServer, a small containerised API collecting logs from several machines
  • Tests, unit and integration tests on the engine

What parallelism actually cost

Going from sequential to parallel is not about launching jobs at the same time: it is the moment when rules that used to be implicit have to be written down, because nothing waits its turn any more.

  • Each job runs in its own task, with a cancellation token for stop and a wait handle for pause, which only takes effect once the current file is done, otherwise you leave a half-written copy behind
  • Priority files are arbitrated by a coordinator shared across every job: no ordinary file starts while a priority extension is still queued, whichever job holds it
  • Bandwidth is protected by a global semaphore: past a configurable threshold, only one large file moves at a time
  • The encryption tool is guarded by a named system mutex, making it unique machine-wide rather than merely process-wide
  • An automatic pause triggers if the client's business software is detected, resuming when it closes

What I took away

  • MVVM: why separating view from logic changes everything when v2 lands
  • Concurrency is designed in, not bolted on: the cross-job rules of v3 simply did not exist while everything ran one after another
  • An architecture is judged on its second version, not its first
  • Technical documentation and team delivery on an imposed schedule
All projects