Generally some type of modular design is required. A monolithic design, by contrast, tightly couples its components, making changes difficult. Modern object-oriented languages provide several features useful for building architectures, including encapsulation, inheritance, and polymorphism. In the context of simulations, encapsulation allows interchanging solvers that may need conflicting internal data structures. Inheritance permits the abstraction of common features of different types of solver, increasing the reuse of code.
Polymorphism allows the substitution of different solvers that handle the same type of physics.
However, object-oriented architectures can be massive and unwieldy, requiring application developers to adopt a framework that is far too general for their needs. Also, poorly conceived inheritance structures can be too rigid, defeating the intent to build reusable code. Component-based architectures address these issues by providing the means for software components to describe themselves to each other in a standard way. In this figure, solid lines with triangles denote inheritance relationships, while dashed lines indicate instantiation relationships. Each box represents a class, which supplies data structures to its subclasses and methods to its calling classes.