README.md and passing tests.You’ll build a small, testable Java 17 app that demonstrates packages, interfaces, encapsulation, and access control (Module 1 core skills). You’ll also practice directory structure, basic testing, and a minimal CLI (or `main`) entry point.
 
project/
  README.md
  pom.xml (or build.gradle)
  src/
    main/
      java/
        com/yourname/oop/module1/
          App.java
          model/
          service/
          repo/
    test/
      java/
        com/yourname/oop/module1/
          AppTest.java
 
Set your base package:com.yourname.oop.module1(replaceyourname)
model/Student (id, name, email) - fields private, validate in constructor/setters.model/Course (code, title).model/Enrollment (studentId, courseCode, status).
// repo/Repository.java
package com.yourname.oop.module1.repo;
import java.util.*;
public interface Repository<T, ID> {
    T save(T entity);
    Optional<T> findById(ID id);
    List<T> findAll();
    boolean deleteById(ID id);
}
                
            
// repo/InMemoryRepository.java
package com.yourname.oop.module1.repo;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class InMemoryRepository<T, ID> implements Repository<T, ID> {
    private final Map<ID, T> store = new ConcurrentHashMap<>();
    private final java.util.function.Function<T, ID> idExtractor;
    public InMemoryRepository(java.util.function.Function<T, ID> idExtractor) {
        this.idExtractor = Objects.requireNonNull(idExtractor);
    }
    @Override public T save(T entity) {
        ID id = idExtractor.apply(entity);
        if (id == null) throw new IllegalArgumentException("Entity id cannot be null");
        store.put(id, entity);
        return entity;
    }
    @Override public Optional<T> findById(ID id) { return Optional.ofNullable(store.get(id)); }
    @Override public List<T> findAll() { return new ArrayList<>(store.values()); }
    @Override public boolean deleteById(ID id) { return store.remove(id) != null; }
}
                
            service/EnrollmentService that uses repositories to enroll a student, list enrollments, drop course, etc.App.java): minimal CLI / demo that:
        System.out.println is fine.
// App.java
package com.yourname.oop.module1;
import com.yourname.oop.module1.model.*;
import com.yourname.oop.module1.repo.*;
import java.util.*;
public class App {
    public static void main(String[] args) {
        Repository<Student, String> students =
            new InMemoryRepository<>(Student::id);
        Repository<Course, String> courses =
            new InMemoryRepository<>(Course::code);
        students.save(new Student("s-1", "Ava", "ava@example.com"));
        courses.save(new Course("CS101", "Intro to CS"));
        System.out.println("Students: " + students.findAll().size());
        System.out.println("Courses: " + courses.findAll().size());
    }
}
// model/Student.java
package com.yourname.oop.module1.model;
import java.util.Objects;
public final class Student {
    private final String id;
    private String name;
    private String email;
    public Student(String id, String name, String email) {
        this.id = Objects.requireNonNull(id);
        setName(name);
        setEmail(email);
    }
    public String id() { return id; }
    public String name() { return name; }
    public String email() { return email; }
    public void setName(String name) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("name");
        this.name = name.trim();
    }
    public void setEmail(String email) {
        if (email == null || !email.contains("@")) throw new IllegalArgumentException("email");
        this.email = email.trim();
    }
}
// AppTest.java
package com.yourname.oop.module1;
import com.yourname.oop.module1.model.Student;
import com.yourname.oop.module1.repo.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class AppTest {
    @Test
    void canSaveAndFindStudent() {
        Repository<Student, String> students = new InMemoryRepository<>(Student::id);
        Student s = new Student("s-1", "Ava", "ava@example.com");
        students.save(s);
        assertTrue(students.findById("s-1").isPresent());
    }
}
Build/Run:
mvn -q -DskipTests=false test && mvn -q -DskipTests package./gradlew test buildmodel: make fields private, expose behavior/getters.App thin; move rules to services.com.yourname.oop.module1.* with clear subpackages.README.md (how to build/run; your design notes)com/yourname/oop/module1/...module1-project-yourname.zipRepository<T,ID> interface?package-private preferable to public?