https://github.com/ckdevrel/solid-principles-flutter
https://github.com/ckdevrel/solid-principles-flutter
Last synced: 17 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/ckdevrel/solid-principles-flutter
- Owner: ckdevrel
- License: unlicense
- Created: 2019-12-19T00:46:20.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2019-12-19T03:28:43.000Z (about 6 years ago)
- Last Synced: 2024-11-04T01:32:59.420Z (over 1 year ago)
- Homepage: https://takeoffandroid.github.io/solid-principles-flutter
- Size: 19.5 KB
- Stars: 15
- Watchers: 2
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Flutter Solid Principles
## S — The Single Responsibility Principle (SRP):
### Bad
```dart
@override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
body: FutureBuilder(
future: getFeedsFromApi(),
builder: (context, snapshot) {
switch(snapshot.connectionState){
case ConnectionState.waiting:
return EmptySpendsPage();
case ConnectionState.none:
return EmptySpendsPage();
case ConnectionState.active:
return EmptySpendsPage();
case ConnectionState.done:
return ListView.builder(
itemCount: snapshot.data == null ? 0 : snapshot.data.length,
itemBuilder: (context, position) {
FeedItem feedItem = snapshot.data[position];
return null;
});
}
}
)
),
);
}
```
### Good
```dart
@override
Widget build(BuildContext context) {
bloc.add(NoParams());
return Scaffold(
body: BlocBuilder(
bloc: bloc,
builder: (BuildContext context, FeedsState feedState) {
if (feedState is FeedsLoading) {
return Center(child: CircularProgressIndicator());
} else if (feedState is FeedsError) {
return Text('Ayo! Error');
} else if (feedState is FeedsLoaded) {
return FeedList(feeds: feedState.feedItems);
}
return Container(
color: Colors.orangeAccent,
height: double.infinity,
width: double.infinity);
}),
);
}
```
## O — The Open-Closed Principle (OCP)
### Bad
```dart
void main() {
MileageCalculator mileageCalculator = new MileageCalculator();
mileageCalculator.showMileage(new Bike());
}
class MileageCalculator {
void showMileage(dynamic anyVehicle) {
if(anyVehicle is Bike) {
print(anyVehicle.getBikeMileage());
} else if(anyVehicle is Car) {
print(anyVehicle.getCarMileage());
}
}
}
class Bike {
String getBikeMileage() => "50";
}
class Car {
String getCarMileage() => "12";
}
```
### Good
```dart
void main() {
MileageCalculator mileageCalculator = new MileageCalculator();
mileageCalculator.showMileage(new Car());
}
class MileageCalculator {
void showMileage(Vehicle vehicle) {
print(vehicle.getMileage());
}
}
class Bike extends Vehicle {
String getMileage() => "50";
}
class Car extends Vehicle {
String getMileage() => "12";
}
abstract class Vehicle {
String getMileage();
}
```
## L - The Liskov Substitution Principle (LSP)
### Bad
```dart
void main() {
StatelessWidget adapter = new StatelessWidget();
adapter.select(new RadioButtonWidget());
}
class StatelessWidget {
void select(ClickListener clickListener) {
if (clickListener is ListItemWidget) {
clickListener.changeTheBackground();
} else if (clickListener is RadioButtonWidget) {
clickListener.check();
}
clickListener.onClick(1);
}
}
mixin ClickListener {
void onClick(int position);
}
class ListItemWidget implements ClickListener {
@override
void onClick(int position){
print("Clicked list item $position");
}
void changeTheBackground() {
print("Change the background color of the item view");
}
}
class RadioButtonWidget implements ClickListener {
@override
void onClick(int position){
print("Clicked radio button $position");
}
void check() {
print("Enable the radio button");
}
}
```
### Good
```dart
void main() {
StatelessWidget adapter = new StatelessWidget();
adapter.select(new RadioButtonWidget());
}
class StatelessWidget {
void select(ClickListener clickListener) {
clickListener.onClick(1);
}
}
mixin ClickListener {
void onClick(int position);
}
class ListItemWidget implements ClickListener {
@override
void onClick(int position){
print("Clicked list item $position");
_changeTheBackground();
}
void _changeTheBackground() {
print("Change the background color of the item view");
}
}
class RadioButtonWidget implements ClickListener {
@override
void onClick(int position){
print("Clicked radio button $position");
_check();
}
void _check() {
print("Enable the radio button");
}
}
```
## I — The Interface Segregation Principle (ISP):
### Bad
```dart
class ImageViewWidget with OnClickListener {
@override
void onImageClick(int position) {
// Yes, I have received a callback, go to the next activity.
print("Clicked position is $position");
}
@override
void onRadioButtonClick(int position) {
// This is no longer needed for this activity, but still I have been implemented for no use...
}
}
mixin OnClickListener {
void onImageClick(int position);
void onRadioButtonClick(int position);
}
```
### Good
```dart
class ImageViewWidget with OnImageClickListener {
@override
void onImageClick(int position) {
// Yes, I have received a callback, go to the next activity.
print("Clicked position is $position");
}
}
mixin OnImageClickListener {
void onImageClick(int position);
}
mixin OnRadioButtonClickListener {
void onRadioButtonClick(int position);
}
```
## D - The Dependency Inversion Principle (DIP)
### Bad
```dart
class RepositoryImpl {
List getDataFromApi() {
// do your api call
}
List getDataFromCache() {
// get the data from the database
}
}
```
### Good
```dart
class RepositoryImpl {
RemoteDataSource remoteDataSource;
LocalDataSource locaDataSource;
RepositoryImpl(this.remoteDataSource, this.locaDataSource);
}
abstract class RemoteDataSource {
List getDataFromApi();
}
abstract class LocalDataSource {
List getDataFromCache();
}
class RemoteDataSourceImpl extends RemoteDataSource{
// Lets assume this class has an access to http client
List getDataFromApi(){
// do your api call
}
}
class LocalDataSourceImpl extends LocalDataSource {
// Lets assume this class has an access to database instance
List getDataFromCache(){
// get the data from the database
}
}
```