Explore how software is built

Completed

Modern software development has fundamentally changed from building everything from scratch to assembling applications from existing components. Understanding this component-based approach is essential for effectively implementing and managing software in contemporary development environments.

The component-based software model

Today's applications are built by combining original code with reusable components. Rather than writing every piece of functionality, development teams assemble solutions from:

  • Original business logic code: Custom code that implements specific business requirements, workflows, and unique features that differentiate your application.
  • Open-source libraries and frameworks: Reusable components created and maintained by the community, providing common functionality like data processing, authentication, user interfaces, and communication protocols.
  • Commercial components: Third-party libraries offered by vendors, often providing specialized functionality, support, and guarantees.
  • Integration code: "Glue" code that connects components together, adapts interfaces, and orchestrates interactions between different parts of the system.

Research consistently shows that modern applications consist of approximately 80% existing components maintained outside the project, with only 20% being original code written by the development team. This composition reflects a fundamental shift in how software is created—from building to assembling.

Why software is built this way

The component-based approach provides significant advantages:

Development velocity

Reusing existing components dramatically accelerates development:

  • Proven solutions: Instead of solving problems that others have already solved, teams incorporate battle-tested components that work reliably.
  • Reduced development time: Building a web application framework, database driver, or authentication system from scratch would take months or years. Using existing components reduces this to days or hours.
  • Focus on business value: Developers concentrate on unique business logic rather than reinventing common infrastructure.
  • Faster time to market: Applications reach production sooner because teams aren't building every layer from scratch.

Quality and reliability

Well-maintained open-source components often exceed the quality of custom code:

  • Community vetting: Popular open-source projects have thousands of users identifying and reporting issues, leading to robust, reliable code.
  • Expert development: Many open-source projects are created and maintained by experts who specialize in specific problem domains.
  • Continuous improvement: Active projects receive regular updates, bug fixes, and enhancements from contributors worldwide.
  • Production testing: Components used by thousands of applications have been tested in diverse environments and scenarios.

Cost efficiency

Using open-source components reduces development and maintenance costs:

  • No licensing fees: Most open-source components are free to use, avoiding per-seat or per-deployment licensing costs.
  • Shared maintenance burden: Bug fixes and improvements are contributed by the community, reducing your organization's maintenance costs.
  • Reduced staffing needs: Teams don't need specialists for every technology layer because they can incorporate existing expertise through components.
  • Lower total cost of ownership: While commercial components have direct costs, open-source alternatives often provide similar functionality without licensing fees.

Access to innovation

Open-source communities drive technological innovation:

  • Cutting-edge features: Many new technologies and approaches emerge first in open-source projects.
  • Ecosystem effects: Popular frameworks create ecosystems of compatible components, tools, and knowledge.
  • Flexible adoption: Organizations can experiment with new technologies without large financial commitments.
  • Community knowledge: Extensive documentation, tutorials, and community support make adoption easier.

Open-source versus closed-source components

Components come in two fundamental categories based on source code availability:

Open-source components

Open-source code is publicly available for anyone to inspect, use, modify, and often contribute to:

  • Source code visibility: You can examine the actual implementation, understand how the component works, and verify security practices.
  • Community involvement: Many people can contribute improvements, fix bugs, and add features.
  • License-governed usage: Open-source licenses specify permitted uses, ranging from unrestricted use to requirements that derivative works share the same license.
  • Transparency: Security researchers, developers, and users can audit code for vulnerabilities, backdoors, or quality issues.

Popular open-source components include:

  • Programming languages and runtimes: Python, Node.js, .NET Core, Go, Rust.
  • Web frameworks: React, Angular, Vue.js, Express, Django, Spring Boot.
  • Databases: PostgreSQL, MySQL, MongoDB, Redis, Elasticsearch.
  • Development tools: Visual Studio Code, Git, Docker, Kubernetes.
  • Libraries: Lodash, Moment.js, NumPy, Pandas, TensorFlow.

Closed-source components

Closed-source (proprietary) components provide functionality without making source code available:

  • Binary distribution: Components are provided as compiled binaries or packaged libraries without source code.
  • Vendor control: The creating organization controls updates, features, and licensing terms.
  • Commercial support: Many closed-source components include professional support, service-level agreements, and guaranteed maintenance.
  • Limited transparency: Users cannot inspect implementation details, making security and quality assessments more difficult.

Examples include many commercial database drivers, proprietary SDKs, vendor-specific tools, and specialized industry-specific libraries.

How components are distributed

Packages provide a formalized mechanism for distributing and managing components:

Package structure

  • Binary code: Compiled libraries ready to use in applications.
  • Metadata: Information about the package including name, version, author, and description.
  • Dependencies: List of other packages required for the component to function.
  • License information: Legal terms governing how the package can be used.
  • Documentation: Usage instructions, API references, and examples.

Package ecosystems

Different programming languages have established package ecosystems:

  • npm (Node Package Manager): JavaScript and TypeScript packages, the world's largest package registry with over 2 million packages.
  • PyPI (Python Package Index): Python packages, providing libraries for data science, web development, automation, and more.
  • NuGet: .NET packages for C#, F#, and Visual Basic applications.
  • Maven Central: Java packages for enterprise and Android development.
  • RubyGems: Ruby packages for web applications and automation.
  • Crates.io: Rust packages for systems programming.

Package management tools

Package managers automate downloading, installing, and updating dependencies:

  • Dependency resolution: Automatically determine and install required dependencies.
  • Version management: Track which versions of packages your application uses.
  • Update notifications: Inform developers when newer versions are available.
  • Vulnerability scanning: Some package managers integrate security scanning to identify known vulnerabilities.

The implications of component-based development

While the component-based approach provides enormous benefits, it also introduces challenges:

Dependency management complexity

  • Dependency trees: Your application might directly depend on 20 packages, but those packages depend on others, creating trees of hundreds or thousands of dependencies.
  • Version conflicts: Different components might require incompatible versions of shared dependencies.
  • Update cascades: Updating one component might require updating many others.

Security considerations

  • Inherited vulnerabilities: Security vulnerabilities in any dependency affect your application.
  • Supply chain attacks: Malicious actors might compromise popular packages to attack applications that depend on them.
  • Unmaintained dependencies: Components that are no longer maintained won't receive security updates.

License compliance

  • License obligations: Each open-source license has requirements—some permit unrestricted commercial use, others require sharing your source code.
  • License proliferation: An application might incorporate hundreds of packages with dozens of different licenses.
  • Compliance burden: Organizations must track license obligations and ensure compliance.

Operational dependencies

  • External hosting: Many applications depend on packages hosted on public registries that could experience outages.
  • Registry availability: If a public registry becomes unavailable, builds and deployments might fail.
  • Package removal: Authors can sometimes remove packages from public registries, breaking applications that depend on them.

Understanding how modern software is built with components provides essential context for the security, legal, and operational concerns that organizations must address when implementing open-source software. The remaining units in this module explore these concerns and strategies for managing them effectively.