Çapraz Platform Proje Yapısı: Kod Organizasyonunda Best Practice
Flutter veya React Native'de kod organizasyonu, projenin ölçeklenebilirliğini ve bakımını doğrudan etkiler. Kötü yapı, ekip içinde karışıklığa, kod tekrarına ve hata ayıklamada zorluklara yol açar.
Öneri olan yapı her özelliği (feature) kendi klasörüne koymaktır:
1lib/2├── features/3│ ├── auth/4│ │ ├── data/5│ │ │ ├── datasources/6│ │ │ ├── models/7│ │ │ └── repositories/8│ │ ├── domain/9│ │ │ ├── entities/10│ │ │ ├── repositories/11│ │ │ └── usecases/12│ │ └── presentation/13│ │ ├── bloc/ (veya provider)14│ │ ├── pages/15│ │ └── widgets/16│ ├── home/17│ └── profile/18├── core/19│ ├── constants/20│ ├── utils/21│ ├── theme/22│ └── network/23└── main.dartHem Android hem iOS'ta çalışan mantığı core/ klasöründe tutun. Platform-spesifik kod ise android/ ve ios/ klasörlerinde kalır.
Bir sayaç uygulamasında yapı şöyle olur:
lib/features/counter/presentation/bloc/counter_bloc.dart:
1import 'package:flutter_bloc/flutter_bloc.dart';23class CounterBloc extends Bloc<CounterEvent, int> {4CounterBloc(): super(0) {5on<IncrementEvent>((event, emit) {6emit(state + 1);7});8on<DecrementEvent>((event, emit) {9emit(state - 1);10});11}12}1314abstract class CounterEvent {}15class IncrementEvent extends CounterEvent {}16class DecrementEvent extends CounterEvent {}lib/features/counter/presentation/pages/counter_page.dart:
1import 'package:flutter/material.dart';2import 'package:flutter_bloc/flutter_bloc.dart';3import '../bloc/counter_bloc.dart';45class CounterPage extends StatelessWidget {6@override7Widget build(BuildContext context) {8return Scaffold(9appBar: AppBar(title: Text('Sayaç')),10body: Center(11child: BlocBuilder<CounterBloc, int>(12builder: (context, count) {13return Text('Sayı: $count', style: TextStyle(fontSize: 32));14},15),16),17floatingActionButton: Row(18mainAxisAlignment: MainAxisAlignment.end,19children: [20FloatingActionButton(21onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),22child: Icon(Icons.add),23),24SizedBox(width: 10),25FloatingActionButton(26onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),27child: Icon(Icons.remove),28),29],30),31);32}33}Beklenen çıktı: Sayfa açıldığında "Sayı: 0" görünür. Artı butonuna basınca 1, eksi butonuna basınca -1 olur.
- Dart dosyaları:
snake_case(örn:counter_bloc.dart) - Sınıf adları:
PascalCase(örn:CounterBloc) - Değişkenler:
camelCase(örn:counterValue)
İyi bir yapı, geliştiricilerin hızlı yer bulmasını sağlar. Feature-based klasörleme, Clean Architecture ilkelerine uygun bir yaklaşımdır. Küçük projeler için basit tutabilir, büyüdükçe bu yapıya geçiş kolay olur.
5 yorum
linter falan da kurulur ama takım bunu ignore etmeye başlayınca ne faydası kalır ya ya da
doğru bence de o yüzden şeyi automatize etmek lazım linter ya da code generation tool
template hazırlamak güzel ama sonra kimse okumaz be dosya şablonu falan da kimse kullanmaz gerçek hayatta
aynen bu yüzden baştan bir template veya convention document hazırlamak gerekiyor yoksa 3 ay sonra her klasörde farklı bir sistem oluyor
hadi canım feature başına klasör açmak doğru ama sonra herkes kendi proje yapısını