The post argues that Erlang modules primarily serve as namespaces, offering a way to organize code and avoid naming collisions, especially in large projects with multiple contributors. While modules can enforce information hiding through opaque data types, this isn't their primary purpose in Erlang, and the author contends that compile-time dependency checking and separate compilation, often cited as reasons for modules, are less relevant due to Erlang's dynamic nature and hot code loading capabilities. The author suggests that simpler projects might not benefit from modules, potentially introducing unnecessary complexity, and argues that their main value lies in preventing name clashes in complex systems.
This 1972 paper by Parnas compares two system decomposition strategies: one based on flowcharts and step-wise refinement, and another based on information hiding. Parnas argues that decomposing a system into modules based on hiding design decisions behind interfaces leads to more stable and flexible systems. He demonstrates this by comparing two proposed modularizations of a KWIC (Key Word in Context) indexing system. The information hiding approach results in modules that are less interconnected and therefore less affected by changes in implementation details or requirements. This approach prioritizes minimizing inter-module communication and dependencies, making the resulting system easier to modify and maintain in the long run.
HN commenters discuss Parnas's modularity paper, largely agreeing with its core principles. Several highlight the enduring relevance of information hiding and minimizing inter-module dependencies to reduce complexity and facilitate change. Some commenters share anecdotes about encountering poorly designed systems violating these principles, reinforcing the paper's importance. The concept of "secrets" as the basis of modularity resonated, with discussions about how it applies to various levels of software design, from low-level functions to larger architectural components. A few commenters also touch upon the balance between pure theory and practical application, acknowledging the complexities of real-world software development.
Go 1.21 introduces a new mechanism for building more modular and extensible WebAssembly applications. Previously, interacting with JavaScript from Go WASM required compiling all the code into a single, large WASM module. Now, developers can compile Go functions as individual WASM modules and dynamically import and export them using JavaScript's standard module loading system. This allows for creating smaller initial downloads, lazy-loading functionalities, and sharing Go-defined APIs with JavaScript, facilitating the development of more complex and dynamic web applications. This also enables developers to build extensions for existing WASM applications written in other languages, fostering a more interconnected and collaborative WASM ecosystem.
HN commenters generally expressed excitement about Go's new Wasm capabilities, particularly the ability to import and export functions, enabling more dynamic and extensible Wasm applications. Several highlighted the potential for creating plugins and modules with Go, simplifying development and deployment compared to current WebAssembly workflows. Some discussed the implications for server-side Wasm and potential performance benefits. A few users raised questions about garbage collection and memory management with this new functionality, and another thread explored comparisons to JavaScript's module system and the potential for better tooling around Wasm. Some expressed concerns about whether it's better to use Go or Rust for Wasm development, and there was an insightful dialogue comparing wasmexport
with previous approaches.
The Hacker News post discusses whether any programming languages allow specifying package dependencies directly within import or include statements, rather than separately in a dedicated dependency management file. The original poster highlights the potential benefits of this approach, such as improved clarity and ease of understanding dependencies for individual files. They suggest a syntax where version numbers or constraints could be incorporated into the import statement itself. While no existing mainstream languages seem to offer this feature, some commenters mention related concepts like import maps in JavaScript and conditional imports in some languages. The core idea is to make dependency management more localized and transparent at the file level.
The Hacker News comments discuss the pros and cons of specifying package requirements directly within import statements. Several commenters appreciate the clarity and explicitness this would bring, as it makes dependencies immediately obvious and reduces the need for separate dependency management files. Others argue against it, citing potential drawbacks like redundancy, increased code verbosity, and difficulties managing complex dependency graphs. Some propose alternative solutions, like embedding version requirements in comments or using language-specific mechanisms for dependency specification. A few commenters mention existing languages or tools that offer similar functionality, such as Nix and Dhall, pointing to these as potential examples or inspiration for how such a system could work. The discussion also touches on the practical implications for tooling and build systems, with commenters considering the impact on IDE integration and compilation processes.
Summary of Comments ( 47 )
https://news.ycombinator.com/item?id=43554444
HN users discuss the merits and drawbacks of modules, primarily in the context of Erlang. Some argue that modules, while offering namespacing and code organization, introduce unnecessary complexity, especially for smaller projects. They suggest that a simpler, record-based approach could suffice in some cases. Others highlight the crucial role of modules in managing larger codebases, facilitating separate compilation, and enabling code reuse. The idea of modules primarily as compilation units is also raised, emphasizing their importance for managing dependencies and build processes. Several commenters discuss the potential of a hybrid approach, offering lighter alternatives to full modules where appropriate, but acknowledging the value of modules for large, complex systems. The Erlang perspective, with its emphasis on lightweight processes and message passing, influences the discussion.
The Hacker News post titled "Why do we need modules at all? (2011)" links to a discussion on the Erlang mailing list about the necessity of modules. The comments on Hacker News explore various facets of this question, expanding on the points raised in the original email thread.
Several commenters discuss the role of modules in organizing code and providing namespaces. One commenter highlights how modules are essential for managing large codebases by breaking them into smaller, more manageable pieces. They argue that without modules, functions would exist in a global namespace, leading to naming collisions and making it difficult to reason about the code's structure.
Another commenter points out that modules can act as compilation units and facilitate separate compilation, improving build times and allowing for dynamic loading of code. This is particularly relevant to Erlang, given its focus on hot code loading.
The idea of modules enforcing code structure and acting as a form of documentation is also mentioned. Commenters argue that modules help to define clear interfaces and encapsulate implementation details. This improves readability and makes it easier for developers to understand and work with the code.
One commenter draws an analogy with object-oriented programming, suggesting that modules in Erlang serve a similar purpose to classes in OOP by grouping related functions and data. This analogy isn't perfect, as Erlang doesn't have objects in the traditional sense, but it illustrates the organizational role of modules.
The discussion also touches on the trade-offs of using modules. One comment notes that while modules provide structure, they can also introduce complexity, especially in dynamically typed languages where module boundaries can make it harder to refactor code.
A recurring theme in the comments is the importance of modules for managing dependencies and reducing coupling between different parts of a system. By explicitly defining dependencies through module imports, developers can create more modular and maintainable code.
Finally, some comments mention the relevance of the discussion to Erlang's specific design and features. The lightweight nature of Erlang processes and the emphasis on concurrency are cited as factors that influence the role and importance of modules in the language.