The application follows a layered architecture pattern with clear separation of concerns:
MakeMyDriveFun/
โโโ Domain/ # Business Logic Layer
โ โโโ Entities/ # Domain models
โ โโโ UseCases/ # Business use cases
โ โโโ Repositories/ # Repository protocols
โโโ Data/ # Data Layer
โ โโโ DataSources/ # Remote/Local data sources
โ โโโ Models/ # Data Transfer Objects (DTOs)
โ โโโ Repositories/ # Repository implementations
โโโ Infrastructure/ # External Dependencies
โ โโโ Network/ # Network services
โ โโโ Location/ # Location services
โโโ Presentation/ # UI Layer
โ โโโ RouteSearch/ # Route search feature
โ โโโ FunLocations/ # Fun locations feature
โ โโโ Common/ # Shared UI components
โโโ DI/ # Dependency Injection
- Entities: Core business objects (
Route,RoutePoint,RouteRequest) - Use Cases: Business logic implementations (
GetRouteUseCase) - Repository Protocols: Abstractions for data access
- DTOs: Data transfer objects for API communication
- Data Sources: Remote API data sources
- Repository Implementations: Concrete repository implementations
- Network Service: HTTP client for API communication
- Location Service: Core Location wrapper
- View Controllers: UIKit view controllers
- View Models: MVVM pattern implementation
- UI Components: Custom UI elements
- DependencyContainer: Service locator pattern for dependency management
- Each class has a single, well-defined purpose
- View controllers only handle UI logic
- Use cases contain only business logic
- Data sources only handle data fetching
- Classes are open for extension but closed for modification
- Protocol-based architecture allows easy testing and mocking
- High-level modules don't depend on low-level modules
- Both depend on abstractions (protocols)
- Dependencies are injected, not created
- Protocols are focused and specific
- Clients depend only on interfaces they use
- Implementations can be substituted without breaking functionality
- Mock implementations for testing
- Monolithic view controllers with mixed responsibilities
- Direct API calls from UI components
- Tight coupling between layers
- Difficult to test and maintain
- โ Separation of Concerns: Each layer has a clear responsibility
- โ Testability: Protocol-based design enables easy unit testing
- โ Maintainability: Code is organized and follows consistent patterns
- โ Scalability: New features can be added without affecting existing code
- โ Error Handling: Comprehensive error handling throughout the application
- โ Async/Await: Modern Swift concurrency patterns
- โ Constants: Centralized configuration and constants
- Input start and end addresses
- Select departure and return dates
- Specify maximum route deviation
- Real-time location services integration
- Display points of interest along the route
- Categorized location types
- Detailed location information
- Open
MakeMyDriveFun.xcodeprojin Xcode - Select your development team in Signing & Capabilities (if needed)
- Choose a simulator or device
- Build and run the project
โ Build Status: The project compiles successfully with no errors!
The new architecture makes testing straightforward:
// Example unit test for GetRouteUseCase
class GetRouteUseCaseTests: XCTestCase {
func testExecuteWithValidRequest() async throws {
// Given
let mockRepository = MockRouteRepository()
let useCase = GetRouteUseCase(repository: mockRepository)
let request = RouteRequest(...)
// When
let result = try await useCase.execute(request: request)
// Then
XCTAssertEqual(result.points.count, 5)
}
}- User Interaction โ View Controller
- View Controller โ View Model
- View Model โ Use Case
- Use Case โ Repository (Protocol)
- Repository โ Data Source
- Data Source โ Network Service
- Network Service โ API
- Response flows back through the same layers
- Swift 5.0+
- UIKit - UI framework
- MapKit - Map integration
- Core Location - Location services
- URLSession - Network requests
- Async/Await - Concurrency
- MVVM - Presentation pattern
- Maintainability: Easy to modify and extend
- Testability: Each layer can be tested independently
- Readability: Clear code structure and naming conventions
- Scalability: Easy to add new features
- Reusability: Components can be reused across features
- Flexibility: Easy to swap implementations
- Add Core Data for local persistence
- Implement Combine for reactive programming
- Add unit and integration tests
- Implement caching strategies
- Add analytics and logging
- Implement offline support
- โ Loading Indicator: Added proper loading state with button text changes and user interaction blocking
- โ API Response Format: Fixed decoding error by updating DTOs to match API response structure
- โ Input Validation: Added validation to prevent API calls with empty required fields
- โ Debug Logging: Added network request/response logging for easier debugging
- โ Location Permissions: Fixed Info.plist location permission keys
- โ Keyboard Handling: Added proper keyboard dismissal and text field navigation
The app now correctly handles the API response format from https://makedrivefunbr.vercel.app/get-route which returns data wrapped in an ai_response object.
You can test the API directly using:
curl -X POST \
https://makedrivefunbr.vercel.app/get-route \
-H 'Content-Type: application/json' \
-d '{
"start_address": "Praรงa da Sรฉ, Sรฃo Paulo, SP",
"end_address": "Praia de Copacabana, Rio de Janeiro, RJ",
"date_of_going": "2025-07-01",
"date_of_returning": "2025-07-10",
"max_route_desviation": "30"
}'This refactored architecture provides a solid foundation for building scalable iOS applications while maintaining clean, testable, and maintainable code.