All work

Flashcards · University project

A study app built around how memory works

A flashcards app built around two evidence-based learning methods, active recall and spaced repetition, taken through the full development cycle: requirements, data model, architecture and a working JSP application, delivered by a team of four.

My role

Requirements, data & backend (team of 4)

Context

Information Systems Development & Architecture, AUEB

Timeline

Delivered Jan 2024

Team

4 students

Illustration of a flashcard deck with tags for active recall and spaced repetition, and a timeline showing a card returning less often the better it is remembered

Why this project is here

This is a university project delivered with three teammates. It earns a place here because it is the one piece of my work where the entire software development lifecycle is visible in a single deliverable, covering requirements, data model, architecture, object design and a set of test cases, and because it was built around a product idea with research behind it rather than being a standard CRUD exercise.

Choosing the learning method, not just building the app

Flashcards themselves are a commodity, since every study app has them. Before any of us wrote a line of code, we made a requirements decision that shaped everything downstream: which learning method the product would be built around, because that determines what the scheduling logic has to do. We chose two with real evidence behind them:

  • Active recall. The user tries to produce the answer from memory before seeing it, rather than passively re-reading it. This is the method that genuinely strengthens memory, whereas re-reading mostly produces a false sense of familiarity.
  • Spaced repetition. A card is shown again on a schedule calculated from how well and how quickly the user remembered it last time, rather than on a fixed daily cycle. Cards the user knows well appear less often, while difficult ones return sooner.

Both methods only work if the product tracks per-user, per-card history. That turned "build a flashcards app" into "design a data model that can drive a scheduling algorithm", a considerably harder problem.

4team members
2learning-science mechanics built in
4core entities modelled
5SDLC artifacts delivered

Requirements, as use cases

Every screen traces back to a documented use case with an actor, a goal, the flow a developer could build straight from, and the alternative flows covering everything that can go wrong along the way. One of them:

Use case

Create flashcard

Actor
User
Goal
Create a new flashcard and add it to a selected deck.
Trigger
The user chooses to create a new flashcard.

The user creates a flashcard by selecting the destination deck and providing the question, answer, and optionally a hint.

Preconditions
  • The user is authenticated.
  • The system can retrieve the user's available decks.
Postconditions
Success
  • A new flashcard is created.
  • The flashcard is associated with the selected deck.
  • The flashcard is available for future study.
Failure
  • No flashcard is created.
  • Any information entered but not successfully submitted is not persisted.
Basic flow, main success scenario
  1. The user chooses to create a flashcard.
  2. The system presents the available decks.
  3. The user selects the deck to which the flashcard will be added.
  4. The system presents the flashcard creation form.
  5. The user enters the question.
  6. The user enters the answer.
  7. The user optionally enters a hint.
  8. The user confirms the creation.
  9. The system validates the required information.
  10. The system creates the flashcard and associates it with the selected deck.
  11. The system confirms that the flashcard has been created successfully.
Alternative flows

A1 Decks cannot be loaded

Starts at step 2
  1. The system cannot retrieve the user's available decks.
  2. The system informs the user that the decks could not be loaded.
  3. The user chooses to retry.
  4. The system attempts to load the decks again.
  5. If successful, the use case resumes at step 3.
  6. If the decks still cannot be loaded, the use case ends without creating a flashcard.

A2 Required information is missing

Starts at step 9
  1. The system determines that the question or answer is missing.
  2. The system informs the user which required information must be provided.
  3. The user provides the missing information.
  4. The use case resumes at step 8.

A3 User cancels creation

Starts any time after step 4 and before step 10
  1. The user chooses to cancel the creation.
  2. The system exits the creation flow without creating the flashcard.
  3. The use case ends.
Special requirements
  • The system must prevent creation of a flashcard without a question and answer.
  • The hint is optional.
  • The flashcard must belong to exactly one selected deck.

What the app remembers about every card

This is the part of the project I would point to first. Spaced repetition sounds like an algorithm, and it is not. It falls out of remembering three simple things for every card, for every learner: how hard it felt last time, when they last saw it, and when it should come back. Decide those three well and the question "when does this card reappear?" answers itself. Decide them badly and no amount of clever scheduling code will rescue it.

Diagram of the review loop: the learner answers a card, the app updates what it knows about that card, and the card is scheduled to come back sooner if it was hard or later if it was easy
The three-step loop behind every review. The whole schedule rests on those three facts, kept per learner and per card, and nothing else.

Why this is a product decision, not a technical one

It is a small, concrete example of a principle I use often: a feature that sounds like an algorithm is frequently just a question of what you decide to remember. Settling those three facts up front made the scheduling straightforward to build, and settling them badly would have made it close to impossible.

Architecture: three separated layers

The app is a classic JSP/Servlet stack, and we kept the three layers strictly separated: JSP pages for presentation, Servlet controllers for the application layer, and DAO classes talking to the database. Every page has a matching controller (CreateFlashcard.jspCreateFlashcardController.jsp), and every entity has a matching DAO (FlashCardDAO.java, DeckDAO.java, UserDeckDAO.java). Nothing in the presentation layer talks to the database directly.

Diagram of three strictly separated layers: JSP pages for presentation, Servlet controllers for the application layer, and DAO classes for data, with the presentation layer never allowed to reach the database directly
Every page has a matching controller, and every entity has a matching DAO. The one rule that mattered most: nothing in the presentation layer talks to the database directly.

Testing and the rest of the cycle

The deliverable also included a structured set of test cases covering the core flows, namely creating and answering flashcards, deck management and the statistics views. They were written the same way as the use cases, with precondition, steps and expected result. Combined with the use case model, the data model and the two diagrams above, the project covers every stage of a classical development lifecycle on a single working product.

What I carried forward

  • Decide what to remember before deciding what to build. Spaced repetition is not code you write once, it is a small set of facts you choose to keep. I now look for this pattern regularly, asking whether the hard part of a feature is really a question of what the product needs to remember.
  • Choose a product method with evidence behind it. Building around active recall and spaced repetition rather than a generic flashcard list is a small decision that changes what the entire schema has to support. I applied the same habit of checking the research before shaping the feature to the R.I.R. calculation at OptimaLifts.
Next case study

EzyFlat: a marketplace built around the household, not the listing

Read it