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
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
The user chooses to create a flashcard.
The system presents the available decks.
The user selects the deck to which the flashcard will be added.
The system presents the flashcard creation form.
The user enters the question.
The user enters the answer.
The user optionally enters a hint.
The user confirms the creation.
The system validates the required information.
The system creates the flashcard and associates it with the selected deck.
The system confirms that the flashcard has been created successfully.
Alternative flows
A1 Decks cannot be loaded
Starts at step 2
The system cannot retrieve the user's available decks.
The system informs the user that the decks could not be loaded.
The user chooses to retry.
The system attempts to load the decks again.
If successful, the use case resumes at step 3.
If the decks still cannot be loaded, the use case ends without creating a flashcard.
A2 Required information is missing
Starts at step 9
The system determines that the question or answer is missing.
The system informs the user which required information must be provided.
The user provides the missing information.
The use case resumes at step 8.
A3 User cancels creation
Starts any time after step 4 and before step 10
The user chooses to cancel the creation.
The system exits the creation flow without creating the flashcard.
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.
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.jsp →
CreateFlashcardController.jsp), and every entity has a matching DAO
(FlashCardDAO.java, DeckDAO.java, UserDeckDAO.java). Nothing
in the presentation layer talks to 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