[Question] 19 dependencies seems excessive. Are all really needed?
Closed this issue · 4 comments
Flutter Blue Plus uses 19 dependencies. Edit: actually I misunderstood the output of pub add
, Im not sure the real number, including child dependencies.
As we all know, more dependencies == things break more often == more maintenance == more work!
Can you provide guidance on what these are used for? It would be great to get rid of any unneeded dependencies.
I would be happy to help.
dependencies:
flutter:
sdk: flutter
convert: ^3.0.1
protobuf: ^2.0.1
rxdart: ^0.27.5
collection: ^1.15.0
meta: ^1.7.0
flutter pub add flutter_blue_plus
Resolving dependencies...
async 2.10.0 (2.11.0 available)
characters 1.2.1 (1.3.0 available)
collection 1.17.0 (1.17.1 available)
+ convert 3.1.1
+ fixnum 1.1.0
+ flutter_blue_plus 1.4.0
intl 0.17.0 (0.18.0 available)
js 0.6.5 (0.6.7 available)
matcher 0.12.13 (0.12.15 available)
material_color_utilities 0.2.0 (0.3.0 available)
meta 1.8.0 (1.9.1 available)
path 1.8.2 (1.8.3 available)
path_provider_android 2.0.24 (2.0.25 available)
path_provider_foundation 2.2.1 (2.2.2 available)
+ protobuf 2.1.0
+ rxdart 0.27.7
source_span 1.9.1 (1.10.0 available)
test_api 0.4.16 (0.5.1 available)
win32 3.1.4 (4.1.3 available)
Changed 5 dependencies!
My findings:
Could easily be removed (in order of ease):
- meta: used for a single @immutable annotation in
CharacteristicProperties
- convert: used to encode & decode a few hex strings. Using this library only saves like 10 lines of code...
- collection: only used for
compareAsciiLowerCase
andListEquality
to hash a list. Again, saves like 10 lines of code... - rxdart: used for a single
BehaviorSubject
stream, just to cache the most recent value.
Required:
- flutter: needed for
MethodChannel
andEventChannel
, which are expected / really helpful for platform native extensions.
Difficult to remove:
- protobuf: Of course, we always want tooling for codegen -- it's great for this use case. But do we need protobuf as a runtime dependency? Possibly not. I think if the generated serialization code used the JSON wire-format option, then the generated code might be free-standing using only standard libraries like
org.json
in Java,JSONSerialization
in Swift, andjsonDecode
in Dart. But I am not sure. (Edit: looks like it stills generates very protobuf specific code, lame.) In lieu of that, OpenAPI's generated Dart code just uses json_serializable, and generates really idiomatic Java & Swift code with no dependencies on either platform. Obviously this is a full day's work and maybe not worth the effort, though. But the more I read OpenAPI's generated code, the more I like it! So idiomatic and clean! Edit: See my next comment for an example.
With minimal effort, we could have flutter & protobuf as our only dependencies. And with a bit more effort, only flutter.
Let me know if this interests you! I am happy to submit a PR removing the 4 easiest dependencies. And to experiment with OpenAPI codegen. I think that would be about 1 full days work.
For this protobuf schema:
message MtuSizeRequest {
string remote_id = 1;
uint32 mtu = 2;
}
protobuf dart code:
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: mtu_size_request.proto
import 'dart:core' show int, bool, double, String, List, override;
import 'package:protobuf/protobuf.dart';
class MtuSizeRequest extends GeneratedMessage {
static final BuilderInfo _i = BuilderInfo('MtuSizeRequest')
..aOS(1, 'remoteId')
..a<core.int>(2, 'mtu', PbFieldType.OU3)
..hasRequiredFields = false;
MtuSizeRequest() : super();
MtuSizeRequest.fromBuffer(List<int> i,
[ExtensionRegistry r = ExtensionRegistry.EMPTY])
: super.fromBuffer(i, r);
MtuSizeRequest.fromJson(String i,
[ExtensionRegistry r = ExtensionRegistry.EMPTY])
: super.fromJson(i, r);
MtuSizeRequest clone() => MtuSizeRequest()..mergeFromMessage(this);
BuilderInfo get info_ => _i;
static MtuSizeRequest create() => MtuSizeRequest();
static PbList<MtuSizeRequest> createRepeated() =>
PbList<MtuSizeRequest>();
static MtuSizeRequest getDefault() {
if (_defaultInstance == null) _defaultInstance = MtuSizeRequest._();
return _defaultInstance;
}
static MtuSizeRequest _defaultInstance;
static void $checkItem(MtuSizeRequest v) {
if (v is! MtuSizeRequest) checkItemFailed(v, 'MtuSizeRequest');
}
String get remoteId => $_getS(0, '');
set remoteId(String v) {
$_setString(0, v);
}
bool hasRemoteId() => $_has(0);
void clearRemoteId() => clearField(1);
int get mtu => $_get(1, 0);
set mtu(int v) {
$_setUnsignedInt32(1, v);
}
bool hasMtu() => $_has(1);
void clearMtu() => clearField(2);
}
OpenAPI schema:
components:
schemas:
MtuSizeRequest:
type: object
properties:
remote_id:
type: string
mtu:
type: integer
format: uint32
required:
- remote_id
- mtu
OpenAPI dart code:
import 'package:json_annotation/json_annotation.dart';
part 'mtu_size_request.g.dart';
@JsonSerializable()
class MtuSizeRequest {
final String remote_id;
final int mtu;
MtuSizeRequest({required this.remote_id, required this.mtu});
factory MtuSizeRequest.fromJson(Map<String, dynamic> json) =>
_$MtuSizeRequestFromJson(json);
Map<String, dynamic> toJson() => _$MtuSizeRequestToJson(this);
}
closing. these were removed.