Object-Oriented Design for an In-Memory File System
Problem
Design an in-memory file system that models files and directories, supports basic filesystem operations (create, delete, list, change directory), and keeps common metadata (timestamps, permissions, size). Provide a clean OOD view and an example skeleton implementation.
Solution
1. Requirements Analysis
Functional requirements:
- Represent files and directories with metadata: name, extension, size, timestamps, flags (read-only, hidden, executable).
- Support directory hierarchy (folders containing files and other folders).
- Basic operations: create (file/folder), list contents, change directory, remove files/folders.
- Provide a simple CLI loop for interactive commands (touch, mkdir, ls, cd, rm).
Non-functional requirements:
- In-memory representation (no persistence) with efficient traversal and lookup in a directory.
- Simplicity: the example focuses on clarity rather than full POSIX semantics.
2. Use Case Diagram
Actors: User (interacting via CLI or API).
Use case summary: A User issues commands to create files/folders, list directory contents, change directories, and remove files. The FileSystem maintains the current working directory and enforces directory-only operations.
graph TD subgraph FileSystem UC_Touch(Create File) UC_Mkdir(Create Directory) UC_Ls(List Contents) UC_Cd(Change Directory) UC_Rm(Remove File/Directory) end User --> UC_Touch User --> UC_Mkdir User --> UC_Ls User --> UC_Cd User --> UC_Rm
3. Class Diagram
Core classes and responsibilities:
- File: Value object for files and directories (name, extension, size, timestamps, flags, isFolder, parent, children).
- FileSystem: Root container with current working directory, and operations to create, list, change directory, and remove entries.
- CLI (optional): Simple loop to parse commands and call FileSystem APIs.
classDiagram class File { +String fileName +String extension +long size +boolean isFolder +File parent +Set~File~ children +getName() } class FileSystem { +File root +File current +create(name, isFolder) +list() +changeDirectory(dir) +remove(names) } FileSystem --> File File --> File : children
4. Activity Diagrams
Activity: Create File/Directory
graph TD U[User issues create command] --> S[FileSystem validates current is directory] S --> C[Create File object] C --> A[Set parent and add to children] A --> R[Return success]
Activity: Change Directory
graph TD U[User issues cd command] --> L[Lookup child in current children] L --> F{Found?} F -- Yes --> C[Set current = child] F -- No --> E[Return error]
5. High-Level Code Implementation
Below are cleaned skeletons derived from the original example.
Java
import java.util.*;
public class File {
String fileName = "";
String extension = "";
long size = 0;
Date createdTime = new Date();
Date modifiedTime = new Date();
boolean readOnly = false;
boolean hidden = false;
boolean isExecutable = false;
boolean isFolder = false;
File parent = null;
Set<File> children = new HashSet<>();
public String getName() {
return isFolder ? fileName : fileName + "." + extension;
}
@Override
public String toString() {
String appendix = isFolder ? "/" : "." + extension;
return fileName + appendix;
}
}
public class FileSystem {
File root = new File();
File current = root;
public FileSystem() {
root.fileName = "~";
root.isFolder = true;
}
public boolean create(String name, boolean isFolder) {
if (current.isFolder) {
File newFile = new File();
if (isFolder) {
newFile.fileName = name;
} else {
String[] names = name.split("\\.");
newFile.fileName = names[0];
newFile.extension = names.length > 1 ? names[1] : "";
}
newFile.isFolder = isFolder;
newFile.parent = current;
current.children.add(newFile);
return true;
} else {
System.out.println("Can only create a file under a directory");
return false;
}
}
public void list() {
for (File file : current.children) {
System.out.printf("%5d %40s\n", file.size, file);
}
}
public boolean changeDirectory(String dir) {
if (dir.equals("..") && current.parent != null) {
current = current.parent;
return true;
}
for (File file : current.children) {
if (file.getName().equals(dir) && file.isFolder) {
current = file;
return true;
}
}
return false;
}
public boolean remove(String[] names) {
List<File> filesToRemove = new LinkedList<>();
boolean deleted = false;
for (File file : current.children) {
for (String name : names) {
if (file.getName().equals(name)) filesToRemove.add(file);
}
}
for (File file : filesToRemove) {
current.children.remove(file);
deleted = true;
}
return deleted;
}
}
Python
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Set, Optional
from datetime import datetime
@dataclass
class File:
file_name: str = ""
extension: str = ""
size: int = 0
created_time: datetime = field(default_factory=datetime.now)
modified_time: datetime = field(default_factory=datetime.now)
read_only: bool = False
hidden: bool = False
is_executable: bool = False
is_folder: bool = False
parent: Optional["File"] = None
children: Set["File"] = field(default_factory=set)
def get_name(self) -> str:
return self.file_name if self.is_folder else f"{self.file_name}.{self.extension}"
class FileSystem:
def __init__(self) -> None:
self.root = File(file_name="~", is_folder=True)
self.current = self.root
def create(self, name: str, is_folder: bool) -> bool:
if not self.current.is_folder:
print("Can only create a file under a directory")
return False
new_file = File()
if is_folder:
new_file.file_name = name
else:
parts = name.split('.')
new_file.file_name = parts[0]
new_file.extension = parts[1] if len(parts) > 1 else ''
new_file.is_folder = is_folder
new_file.parent = self.current
self.current.children.add(new_file)
return True
def list(self) -> None:
for f in self.current.children:
print(f.size, f)
def change_directory(self, dir: str) -> bool:
if dir == '..' and self.current.parent:
self.current = self.current.parent
return True
for f in self.current.children:
if f.get_name() == dir and f.is_folder:
self.current = f
return True
return False
References