391 lines
11 KiB
Markdown
391 lines
11 KiB
Markdown
# Project Structure
|
|
|
|
## Overview
|
|
|
|
The `onvif-go` project follows the **Standard Go Project Layout** optimized for a library package. This structure provides clear separation between public APIs, private implementation details, executable commands, and supporting resources.
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
onvif-go/
|
|
├── *.go # Public API files (root level)
|
|
│ ├── client.go # Main ONVIF client
|
|
│ ├── device.go # Device service operations
|
|
│ ├── media.go # Media service operations
|
|
│ ├── ptz.go # PTZ service operations
|
|
│ ├── imaging.go # Imaging service operations
|
|
│ ├── types.go # Public type definitions
|
|
│ ├── errors.go # Error types and handling
|
|
│ └── doc.go # Package documentation
|
|
│
|
|
├── internal/ # Private packages (not importable externally)
|
|
│ └── soap/ # SOAP client implementation
|
|
│ ├── soap.go # SOAP envelope building and parsing
|
|
│ └── soap_test.go # SOAP client tests
|
|
│
|
|
├── discovery/ # Device discovery subpackage (public)
|
|
│ ├── discovery.go # WS-Discovery implementation
|
|
│ └── discovery_test.go # Discovery tests
|
|
│
|
|
├── server/ # ONVIF server implementation (public)
|
|
│ ├── server.go # Main server
|
|
│ ├── device.go # Device service handlers
|
|
│ ├── media.go # Media service handlers
|
|
│ ├── ptz.go # PTZ service handlers
|
|
│ ├── imaging.go # Imaging service handlers
|
|
│ └── soap/ # Server SOAP handling
|
|
│ └── handler.go # SOAP request handler
|
|
│
|
|
├── cmd/ # Command-line applications
|
|
│ ├── onvif-cli/ # Interactive CLI tool
|
|
│ ├── onvif-quick/ # Quick test utility
|
|
│ ├── onvif-server/ # Virtual camera server
|
|
│ ├── onvif-diagnostics/ # Diagnostic tool
|
|
│ └── generate-tests/ # Test generation utility
|
|
│
|
|
├── examples/ # Example applications
|
|
│ ├── device-info/ # Get device information
|
|
│ ├── discovery/ # Discover cameras
|
|
│ ├── ptz-control/ # PTZ operations
|
|
│ ├── imaging-settings/ # Imaging configuration
|
|
│ ├── complete-demo/ # Full feature demo
|
|
│ ├── simplified-endpoint/ # Endpoint format demo
|
|
│ ├── test-server/ # Server testing example
|
|
│ └── .../ # Additional examples
|
|
│
|
|
├── docs/ # Documentation
|
|
│ ├── ARCHITECTURE.md # Architecture overview
|
|
│ ├── PROJECT_STRUCTURE.md # This file
|
|
│ ├── SIMPLIFIED_ENDPOINT.md # Endpoint API docs
|
|
│ └── .../ # Additional documentation
|
|
│
|
|
├── testdata/ # Test fixtures and data
|
|
├── testing/ # Testing helpers
|
|
│
|
|
├── .github/ # GitHub workflows and configs
|
|
│ └── workflows/
|
|
│ └── release.yml # Release automation
|
|
│
|
|
├── go.mod # Go module definition
|
|
├── go.sum # Dependency checksums
|
|
├── Makefile # Build automation
|
|
├── Dockerfile # Container image
|
|
├── README.md # Project readme
|
|
├── CHANGELOG.md # Version history
|
|
├── LICENSE # License information
|
|
├── CONTRIBUTING.md # Contribution guidelines
|
|
├── QUICKSTART.md # Quick start guide
|
|
└── BUILDING.md # Build instructions
|
|
```
|
|
|
|
## Design Principles
|
|
|
|
### 1. Library-First Design
|
|
|
|
As a **library package**, the main API lives at the root level:
|
|
|
|
```go
|
|
import "github.com/0x524a/onvif-go"
|
|
|
|
client, err := onvif.NewClient("192.168.1.100")
|
|
```
|
|
|
|
**Benefits:**
|
|
- Clean, simple import path
|
|
- Follows Go conventions for libraries
|
|
- Easy to discover and use
|
|
- No unnecessary nesting
|
|
|
|
### 2. Internal Package for Private Code
|
|
|
|
The `internal/` directory contains implementation details not intended for external use:
|
|
|
|
```go
|
|
// This import is ONLY available within onvif-go:
|
|
import "github.com/0x524a/onvif-go/internal/soap"
|
|
```
|
|
|
|
**Go's internal package restriction:**
|
|
- Cannot be imported by external projects
|
|
- Enforced by the Go compiler
|
|
- Allows refactoring without breaking changes
|
|
|
|
**What goes in internal/**:
|
|
- SOAP client implementation
|
|
- Protocol-specific details
|
|
- Helper functions not part of public API
|
|
- Implementation details that might change
|
|
|
|
### 3. Subpackages for Additional Features
|
|
|
|
Public subpackages for optional or specialized functionality:
|
|
|
|
```go
|
|
// Discovery subpackage
|
|
import "github.com/0x524a/onvif-go/discovery"
|
|
|
|
// Server subpackage
|
|
import "github.com/0x524a/onvif-go/server"
|
|
```
|
|
|
|
**When to create a subpackage:**
|
|
- Logically separate feature set
|
|
- Can be used independently
|
|
- Different import namespace makes sense
|
|
- Clear, single responsibility
|
|
|
|
### 4. Commands in cmd/
|
|
|
|
Executable applications in `cmd/` directory:
|
|
|
|
```
|
|
cmd/
|
|
├── onvif-cli/ # Main CLI tool
|
|
├── onvif-server/ # Virtual camera
|
|
└── onvif-quick/ # Quick utility
|
|
```
|
|
|
|
**Naming convention:**
|
|
- Directory name = binary name
|
|
- Each cmd has its own `main.go`
|
|
- Can import the library: `import "github.com/0x524a/onvif-go"`
|
|
|
|
**Build commands:**
|
|
```bash
|
|
go build ./cmd/onvif-cli
|
|
go build ./cmd/onvif-server
|
|
```
|
|
|
|
### 5. Examples for Documentation
|
|
|
|
The `examples/` directory demonstrates library usage:
|
|
|
|
**Structure:**
|
|
- Each example is a standalone program
|
|
- Clear, focused demonstration
|
|
- Can be built and run directly
|
|
|
|
**Purpose:**
|
|
- Supplement documentation
|
|
- Show best practices
|
|
- Provide starting points for users
|
|
|
|
### 6. Documentation in docs/
|
|
|
|
Comprehensive documentation in `docs/` directory:
|
|
|
|
- `ARCHITECTURE.md` - Design and architecture
|
|
- `PROJECT_STRUCTURE.md` - This file
|
|
- `SIMPLIFIED_ENDPOINT.md` - Feature documentation
|
|
- Additional guides as needed
|
|
|
|
**Why separate docs/?**
|
|
- Keeps root clean
|
|
- Organized by topic
|
|
- Easy to navigate
|
|
- Scalable structure
|
|
|
|
## Import Patterns
|
|
|
|
### Public API (Root Package)
|
|
|
|
```go
|
|
// Main client functionality
|
|
import "github.com/0x524a/onvif-go"
|
|
|
|
client, err := onvif.NewClient("192.168.1.100",
|
|
onvif.WithCredentials("admin", "password"),
|
|
)
|
|
```
|
|
|
|
### Discovery Subpackage
|
|
|
|
```go
|
|
// Device discovery
|
|
import "github.com/0x524a/onvif-go/discovery"
|
|
|
|
devices, err := discovery.Discover(ctx, 5*time.Second)
|
|
```
|
|
|
|
### Server Subpackage
|
|
|
|
```go
|
|
// Virtual ONVIF server
|
|
import "github.com/0x524a/onvif-go/server"
|
|
|
|
srv := server.NewServer(
|
|
server.WithCredentials("admin", "admin"),
|
|
server.WithAddress(":8080"),
|
|
)
|
|
```
|
|
|
|
### Internal Package (Library Use Only)
|
|
|
|
```go
|
|
// Only usable within onvif-go itself
|
|
import "github.com/0x524a/onvif-go/internal/soap"
|
|
|
|
// External projects CANNOT import internal packages
|
|
```
|
|
|
|
## File Organization Best Practices
|
|
|
|
### Root Package Files
|
|
|
|
Group by service/functionality:
|
|
- `client.go` - Client creation and core functionality
|
|
- `device.go` - Device service methods
|
|
- `media.go` - Media service methods
|
|
- `ptz.go` - PTZ service methods
|
|
- `imaging.go` - Imaging service methods
|
|
- `types.go` - Type definitions
|
|
- `errors.go` - Error types
|
|
- `doc.go` - Package documentation
|
|
|
|
### Test Files
|
|
|
|
Co-located with source:
|
|
- `client_test.go` - Tests for client.go
|
|
- `device_test.go` - Tests for device.go
|
|
- Mirrors source file structure
|
|
|
|
### Large Packages
|
|
|
|
For large packages, consider grouping:
|
|
```
|
|
server/
|
|
├── server.go # Main server
|
|
├── device.go # Device handlers
|
|
├── media.go # Media handlers
|
|
├── ptz.go # PTZ handlers
|
|
├── imaging.go # Imaging handlers
|
|
└── soap/ # SOAP sub-package
|
|
└── handler.go
|
|
```
|
|
|
|
## Comparison with Other Layouts
|
|
|
|
### ❌ Avoid: pkg/ Directory for Libraries
|
|
|
|
```
|
|
# DON'T DO THIS for libraries:
|
|
my-lib/
|
|
└── pkg/
|
|
└── mylib/
|
|
└── mylib.go
|
|
|
|
# Requires: import "github.com/user/my-lib/pkg/mylib"
|
|
```
|
|
|
|
**Why not?**
|
|
- Unnecessary nesting
|
|
- More complex imports
|
|
- Not idiomatic for Go libraries
|
|
- `pkg/` is for applications with multiple packages
|
|
|
|
### ✅ Library Layout (What We Use)
|
|
|
|
```
|
|
onvif-go/
|
|
├── *.go # Public API at root
|
|
└── internal/ # Private implementation
|
|
|
|
# Clean import: import "github.com/user/onvif-go"
|
|
```
|
|
|
|
### 📦 Application Layout (Different Use Case)
|
|
|
|
For applications (not libraries):
|
|
```
|
|
my-app/
|
|
├── cmd/ # Multiple binaries
|
|
├── internal/ # Private app code
|
|
├── pkg/ # Exported libraries from this app
|
|
└── main.go # Or in cmd/
|
|
```
|
|
|
|
## Migration Notes
|
|
|
|
### Recent Changes
|
|
|
|
**Moved SOAP to internal/:**
|
|
- `soap/` → `internal/soap/`
|
|
- Updated imports in:
|
|
- `device.go`
|
|
- `media.go`
|
|
- `ptz.go`
|
|
- `imaging.go`
|
|
- `server/soap/handler.go`
|
|
|
|
**Reason:**
|
|
- SOAP client is an implementation detail
|
|
- Users should interact through high-level API
|
|
- Prevents tight coupling to SOAP specifics
|
|
- Allows future protocol changes
|
|
|
|
### Import Updates
|
|
|
|
**Old:**
|
|
```go
|
|
import "github.com/0x524a/onvif-go/soap"
|
|
```
|
|
|
|
**New:**
|
|
```go
|
|
import "github.com/0x524a/onvif-go/internal/soap"
|
|
```
|
|
|
|
**External users:** No changes needed (they never imported soap directly)
|
|
|
|
## Benefits of This Structure
|
|
|
|
### For Library Users
|
|
|
|
1. **Simple imports**: `import "github.com/0x524a/onvif-go"`
|
|
2. **Clear API**: Public vs private clearly separated
|
|
3. **Stable interface**: Internal changes don't affect users
|
|
4. **Good documentation**: Examples and docs organized
|
|
|
|
### For Contributors
|
|
|
|
1. **Clear organization**: Each file has single responsibility
|
|
2. **Easy navigation**: Logical directory structure
|
|
3. **Safe refactoring**: Internal package allows changes
|
|
4. **Standard layout**: Follows Go conventions
|
|
|
|
### For Maintenance
|
|
|
|
1. **Backward compatibility**: Internal changes don't break users
|
|
2. **Scalability**: Structure supports growth
|
|
3. **Testing**: Co-located tests, separate test utilities
|
|
4. **Documentation**: Organized in docs/
|
|
|
|
## Future Considerations
|
|
|
|
As the project grows:
|
|
|
|
1. **More subpackages**: Analytics, events, recording services
|
|
2. **Additional internal packages**: Caching, connection pooling
|
|
3. **Tool improvements**: Enhanced cmd/ utilities
|
|
4. **Documentation growth**: More guides in docs/
|
|
|
|
The current structure supports these additions naturally.
|
|
|
|
## References
|
|
|
|
- [Standard Go Project Layout](https://github.com/golang-standards/project-layout)
|
|
- [Go Blog: Package names](https://go.dev/blog/package-names)
|
|
- [Effective Go](https://go.dev/doc/effective_go)
|
|
- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
|
|
|
|
## Summary
|
|
|
|
The onvif-go project structure:
|
|
- ✅ Follows Go conventions for libraries
|
|
- ✅ Public API at root level
|
|
- ✅ Internal package for private code
|
|
- ✅ Subpackages for additional features
|
|
- ✅ Clear separation of concerns
|
|
- ✅ Scalable and maintainable
|
|
- ✅ User-friendly imports
|