你好!本文檔包含我對應如何進行發展的政策,程序和標準的個人建議。
項目代碼應與文件夾和逐型文件夾的混合結構結構。
含義在根級別,您的文件夾定義功能。例如:
|-- common/
|-- authentication/
|-- settings/
Common/Core功能包含默認情況下應在任何功能中可用的類,功能或小部件。
因此,這個想法是要使應用程序的功能除以頂級文件夾。
將每個頂級文件夾視為應用程序的單獨飛鏢/飛鏢包,依賴關係或訪問邊界。
因此,如果您在通用文件夾中添加一些內容,則必須問自己,將需要99.%的功能嗎?
如果您將其視為依賴性,則在您的pubspec.yaml中始終聲明共同的依賴性。
因此,在將課程,功能或小部件添加到公共文件夾之前,請問自己:
在每個功能文件夾中,您的文件夾按類型定義。
這是將是功能文件夾的一部分的文件夾類型。
|-- ui/
|-- cubits/
|-- domain_objects/
|-- exceptions/
|-- use_cases
|-- services/
|-- repositories/
|-- data_sources/
|-- dtos/
如果與單個文件有關的一個以上的文件,您可以將它們分組為文件夾,例如文件中的類生成代碼。例如:
|-- authentication/
|---- cubits/
|------ login/
|-------- login_cubit.dart
|-------- login_cubit.freezed.dart
|-------- login_cubit.g.dart
與用戶設備接口相關的代碼,例如:UI PageBuilders,UI屏幕,UI視圖,UI組件。
屏幕是填充整個設備顯示的用戶界面組件,是用戶界面視圖或組件的容器(按鈕,複選框,圖像和ECT)。
另外,屏幕是一個特定的應用程序導航目的地。
指南:
class LoginScreen extends StatelessWidget {
//...fields and constructor...
@override
Widget build ( BuildContext context) {
return Column (
children : < Widget > [
_LoginLogo ,
_LoginForm ,
_LoginActions ,
_LoginFooter
],
);
}
}
// extracted by use case.
class _LoginLogo extends StatelessWidget {}
// extracted by update area.
class _LoginForm extends StatefullWidget {}
// extracted by update area.
class _LoginActions extends StatelesssWidget {}
// extracted by update area.
class _LoginFooter extends StatelessWidget {} login_screen.dart
part 'login_screen_components.dart' ;
class LoginScreen extends StatelessWidget {
//...fields and constructor...
@override
Widget build ( BuildContext context) {
return Column (
children : < Widget > [
_LoginLogo ,
_LoginForm ,
_LoginActions ,
_LoginFooter
],
);
}
}
// Is kept here because it's does not break the 400 max line rule.
class _LoginLogo extends StatelessWidget {} login_screen_components.dart
part of 'login_screen.dart' ;
/// [LoginScreen] 's fields.
class _LoginForm extends StatelessWidget {}
// ************************ Footer ************************
/// [LoginScreen] 's footer.
class _LoginFooter extends StatelessWidget {}
// ************************* ACTIONS *********************************
/// [LoginScreen] 's actions.
class _LoginActions extends StatelessWidget {} class LoginScreen extends StatelessWidget {
@override
Widget build ( BuildContext context) {
return BlocBuilder < LoginCubit , LoginCubitState >(
// Here cubit is not specified either.
builder : ( BuildContext context, LoginCubitState state) {},
);
}
} class SomeWidget extends StatelessWidget {
@override
Widget build ( BuildContext context) {
//...
}
}
class _SubTree1 extends StatelessWidget {}
class _SubTree2 extends StatelessWidget {}
class _SubTree3 extends StatelessWidget {}
class _SubTree4 extends StatelessWidget {} class LoginScreen extends StatelessWidget {
@override
Widget build ( BuildContext context) {
return Column (
childreen : < Widget > [
Button1 (onClick : _openRegisterUser),
Button2 (onClick : _openLogin),
Field (onTextChanged : _onUserNameTextChanged),
],
);
}
void _openRegisterUser () {}
void _openLogin () {}
void _onUserNameTextChanged ( String newText) {}
}視圖是一個不填充整個設備顯示的用戶界面組件,並且是用戶界面視圖或組件的容器(按鈕,複選框,圖像和ECT)。
另外,視圖不是應用程序導航目的地。
指南:
Cubits是包含UI業務邏輯的類,Cubit綁定到代表UI狀態的狀態。
指南建議:
Future < String ?> bookAppointment ( BookingData booking);
Future < bool > login ( String username, String password);CUBIT狀態類代表UI的狀態與給定時間界定。
指南建議:
class LoginState {
bool logginSuceeded // avoid this.
}用於在您的域中製作單個業務操作/目標/工作/任務的類。
指南:
class GetCurrentUserUseCase , class SignInUseCase ;UseCase ;call() ,其中返回類型是執行用例的結果;Repositories , Services或任何其他high level coordinators ;DataSource或Cubit或與DTO或任何其他低級對象進行交互;Cubit或其他UseCases中使用。示例:
class GetCurrentUserUseCase {
final UserRepository _repository;
const GetCurrentUserUseCase ( this ._repository);
Future < User ?> call () async {
await _repository. getCurrentUser ();
}
} class AuthenticateMemberUseCase {
/// Create a [AuthenticateMemberUseCase] .
const AuthenticateMemberUseCase (
/* constructor arguments */
);
/* ... fields ...*/
/// Execute the use case.
Future < TegTask < void >> call ( MemberAuthenticationCredentials credentials) {
return runTaskSafelyAsync < void >(() async {
final bool isEmailValid = credentials.email.isEmail;
if ( ! isEmailValid) {
throw const TegEmailInvalidException ();
}
final bool isConnected = await _hostDeviceInternetService. isConnected ();
if ( ! isConnected) {
throw const TegInternetUnavailableException ();
}
final String ? deviceId = await _hostDeviceInfoRepository. getDeviceId ();
if (deviceId == null ) {
throw const TegDeviceIdUnavailableException ();
}
final PublicPrivateKeyPair keyPair = await _keyGenerator. generate ();
final Member member = await _authService. signIn (
email : credentials.email,
password : credentials.password,
deviceId : deviceId,
publicKey : keyPair.publicKey,
);
await _updateCurrentMemberUseCase (
member : member,
memberPrivateKey : keyPair.privateKey,
deviceId : deviceId,
);
await _saveMemberAuthenticationCredentialsUseCase (credentials);
final TegTask < List < Account >> memberAccountsTask = await _getMemberAccountsUseCase ();
if (memberAccountsTask.failed) {
throw memberAccountsTask.exception;
}
await _updateMemberCurrentAccountUseCase (
member : member,
deviceId : deviceId,
memberPrivateKey : keyPair.privateKey,
account : memberAccountsTask.result.first,
);
});
}
}僅使用CRUD操作提供特定功能或功能範圍的CRUD操作的類,例如:
abstract class BookingRepository {
Futute < Booking > getBookingById ( String id);
Future < List < Booking >> getBookings ();
Future < void > deleteBookingById ( String id);
Future < void > saveBooking ( Booking booking);
}指南建議:
class DefaultBookingRepository implements BookingRepository {
final LocalBookingDataSource local;
final RemoteBookingDataSource remote;
Future < Booking ?> getBookingById ( String id) async {
Booking ? savedBooking = await local. getBookingById (id);
if (savedBooking == null ) {
Booking ? remoteBooking = await remote. getBookingById (id);
if (remoteBooking != null ) {
await local. saveBooking (remoteBooking);
}
return remoteBooking;
}
return savedBooking;
}
//...other operations...
}介面
abstract class BookingRepository {}實施
class DefaultBookingRepository implements BookingRepository {}
class AnonymousBookingRepository implements BookingRepository {}
class PremiumBookingRepository implements BookingRepository {}類別提供特定功能或功能範圍的功能的類,例如:
abstract class AuthenticationService {
Future < void > authenticate ( String username, String password);
//...other functionalities...
}
abstract class AppointmentService {
Future < void > register ( Appointment appointment);
//...other functionalities...
}指南建議。
類實現對本地或遠程數據的數據的訪問。例子
abstract class LocalBookingDataSource {
Futture < void > saveBooking ( Booking booking);
//...other functionalities...
}
abstract class RemoteBookingDataSource {
Future <booking> saveBooking ();
}指南建議:
class SQLiteBookingDataSource implements LocalBookingDataSource {
//...............Implementation................
}
class RestApiBookingDataSource implements RemoteBookingDataSource {
//...............Implementation................
}
class MemoryBookingDataSource implements LocalBookingDataSource {
//...............Implementation................
}數據傳輸對象 - 用於將數據從一個系統傳輸到另一個系統。例子
class ApiRequest {
//...fields...
}
class ApiResponse {
//...fields...
} class SQLiteTableDefinition {
//...fields...
}指南:
class ApiRequest {
//...fields...
factory ApiRequest . fromDO ( DOObject doObject) {
//...mapper code...
}
DOObject toDO () {
//...mapper code...
}
}域對像是業務一部分或其中一部分的數據類表示,它們用於獨立於平台,圖書館或工具來執行業務邏輯。
域對象可以代表一個人,地點,事件,業務流程或概念以及發票,產品,交易甚至人的詳細信息。
指南:
與項目代碼結構相同。
首先是功能名稱,然後是包含文件的assets文件夾。
例子:
|-- authentication/
|---- assets/
|------ password_hidden_icon.svg
|------ forget_password_icon.svg
|------ background.png