The blog post advocates for a layered approach to structuring Go applications, emphasizing separation of concerns and dependency inversion. It proposes organizing code into distinct layers – domain, service, handler – with each layer depending only on the layers beneath it. The domain layer houses core business logic and entities, the service layer orchestrates domain operations and handles application-specific logic, and the handler layer interacts with external systems like databases and HTTP requests. This layered structure promotes testability, maintainability, and clearer understanding of the codebase by enforcing boundaries and reducing dependencies between different parts of the application. This approach differs from strictly hexagonal architecture, allowing the service layer to orchestrate domain logic, and focuses on practical application over strict adherence to architectural patterns.
The blog post argues for an intermediate representation (IR) layer in query compilers between the logical plan and the physical plan, called the "relational algebra IR." This layer would represent queries in a standardized, relational algebra form, enabling greater portability and reusability of optimization rules across different physical execution engines. Currently, optimization logic is often tightly coupled to specific physical plans, making it difficult to adapt to new engines or hardware. By introducing this standardized relational algebra IR, query compilers can achieve better modularity and extensibility, simplifying development and allowing for easier experimentation with new optimization strategies without needing to rewrite code for each backend. This ultimately leads to more efficient query execution across diverse environments.
HN commenters generally agree with the author's premise that a middle tier is missing in query compilers, sitting between logical optimization and physical optimization. This tier would handle "cross-physical plan" optimizations, allowing for better cost-based decisions that consider different physical plan choices holistically rather than sequentially. Some discuss the challenges in implementing this, particularly the explosion of search space and the difficulty in accurately costing plans. Others offer specific examples where such a tier would be beneficial, such as selecting join algorithms based on data distribution or optimizing for specific hardware like GPUs. A few commenters mention existing systems that implement similar concepts, though not necessarily as a distinct tier, suggesting the idea is already being explored in practice. Some debate the practicality of the proposed solution, suggesting alternative approaches like adaptive query execution or learned optimizers.
Summary of Comments ( 16 )
https://news.ycombinator.com/item?id=43740992
Hacker News users generally praised the article for its clear explanation of layered architecture in Go, particularly appreciating the focus on dependency inversion and the practical "domain" layer example. Some debated the merits of layered architecture in general, with a few suggesting alternative approaches like hexagonal architecture or Clean Architecture, noting potential drawbacks like increased boilerplate. A recurring theme was the importance of considering the project's complexity before adopting a layered approach, with simpler projects potentially not needing such strict structure. Others shared related experiences and alternative approaches to organizing Go code, highlighting the "package by feature" method and discussing the challenges of maintaining large, complex codebases. Several commenters also appreciated the author's clear and concise writing style.
The Hacker News post titled "Layered Design in Go" (linking to an article about the same topic) generated several comments discussing the merits and drawbacks of the layered architecture approach in Go, along with alternative suggestions and experiences.
Several commenters appreciate the clarity and simplicity presented in the article. One user found the article a helpful reminder of good software engineering principles, applicable beyond just Go. Another agreed with the author's focus on dependency inversion, highlighting its crucial role in building testable and maintainable software. The conciseness of the article was also praised.
A recurring theme in the comments is the discussion of alternative approaches to layered architecture, particularly hexagonal architecture (also known as ports and adapters). Commenters pointed out the benefits of hexagonal architecture in terms of decoupling business logic from external dependencies, ultimately improving testability and flexibility. Some argued that while layered architecture might be suitable for simpler projects, hexagonal architecture offers greater advantages for more complex applications.
A few comments also delved into the specifics of dependency injection in Go. One commenter suggested using a "wire" tool for compile-time dependency injection, while others discussed the pros and cons of using interfaces for dependency injection. A point was raised about the potential overhead of interfaces in Go and the consideration of using concrete types for dependencies in performance-sensitive scenarios.
The discussion also touched upon the trade-offs between strict layering and practicality. One commenter argued that rigid adherence to layered architecture can sometimes lead to unnecessary abstraction and complexity. The idea of allowing some controlled violation of layering for pragmatic reasons was also proposed.
A few commenters shared their own experiences with layered and hexagonal architectures, offering real-world examples of where each approach proved beneficial. These anecdotal comments provided valuable context to the more theoretical discussions.
Overall, the comments on Hacker News presented a balanced view of layered architecture in Go. While acknowledging its simplicity and usefulness in certain contexts, the commenters also highlighted potential limitations and explored alternative architectural patterns like hexagonal architecture. The discussion was constructive and insightful, offering practical advice and diverse perspectives on software design in Go.