I have a rather large Dart application that uses part and part of so that I don't have to use relative imports. However, the application may have something like this at the entry point file:
part 'file1.dart';
part 'file2.dart';
part 'file3.dart';
part 'some_sub_dir/file1.dart';
part 'some_sub_dir/file2.dart';
part 'some_sub_dir/file3.dart';
part 'some_sub_dir/file4.dart';
part 'some_sub_dir/file5.dart';
part 'some_sub_dir/file6.dart';
...
As far as I know, my IDE (WebStorm) doesn't automatically add a part statement when I create a new class. Is there any way I can avoid having to use so many parts? If not, can the process of adding new parts each time be automated?
I understand your problem as I can and I'll try to answer from my experience in Dart.
As I got it you are trying to keep all (or a lot) project files as parts of one library. It's wrong conception. In Dart library is not big thing. Here is few advices how to organize your files.
Don't try to keep a lot of files as parts of one library. Rather keep each file as separated library.
You can keep few classes in one file. But be sure classes works together for one idea.
You can split one library in few part files only if it has a lot of classes or one class is too big. But be sure all this files should be together in one library.
If you don't know how to combine classes in libraries keep each class in separated library. After days you will get understanding which classes plays together.
If one class from one library has usages in not only library but in other libraries - make it separated library.
Place parts in same folder with main library file.
If library has parts put all library files into separated folder.
Use relative links to parts.
Always use absolute links to other libraries. It will help you to make refactoring in future.
For example, this is a project like TODO list application. So, we have view class:
// This is a view html component class. //
library todolist.list_viewer;
import 'package:todolist/task.dart'; // model class
class ListViewer extends HtmlElement {
// it showes list of tasks
}
class TodoRenderer extends HtmlElement {
// this is a renderer for one todo item
}
And this is a model class:
// This is a todo model task //
library todolist.task;
class TodoProvider {
List<TodoItem> todos;
String addItem(TodoItem new Todo) {
//...
}
}
class TodoItem {
String Author;
DateTime date;
}
It looks simple now, divided into separated libraries. But if we want to add RecId class to keep todo database id it becomes too complex. We should split it in two libraries: todo_provider and todo_model and put RecId class into last one. Now it's good again.
If we wanna add one more model: a User, so each todo item may have executor or author. We can't just put it todo_model. Now we should to combine TodoItem and User classes into model library. So we just rename todo_model class to model and add User class into it.
Or instead last action we can make user_model library to keep User class. And as User model has recId property too we should extract RecId class into separated library.
It's all depends on how our classes big and complex.
I understand that:
part/part of is used to break a library into several parts (scripts). You have visibility to public and private members.
import is to "call/use" another library from your library. You have only visibility to public members of the imported library.
WebStorm can't infer you want a script to be part of your library.
Related
I have a class named _AppColors. it contains all colors used in the application. I want to force developers to read colors from Theme that's why I made this class private. now I want to access this class from two files. but it can be only part of one file. how can I handle this?
app_colors.dart:
part of 'color_extention.dart';
class _AppColors {
...
app_theme.dart
import 'package:flutter/material.dart';
part 'app_colors.dart';
extension MultiThemeColorExtension on ThemeData {
...
color_extention.dart
import 'package:flutter/material.dart';
part 'app_colors.dart';
const TextTheme _textThemeLight = TextTheme(
...
but I have to add part of 'color_extention.dart'; in app_colors.dart which I can't. any solution?
Private symbols are private to the library. Normally a Dart library is a single .dart file, but part is used to specify that a library comprise multiple .dart files (and conversely, part of is used to specify that a .dart file is part of the specified library).
It doesn't make sense for a Dart file to be part of multiple libraries. If you want to share a private class with multiple .dart files, your typical options are:
Make all of those .dart files part of the same library.
Make your class public instead but discourage using them. Packages typically do this by placing internal implementation files in lib/src/ and exporting only the symbols intended for public consumption.
It's possible to add extensions to existing Swift object types using extensions, as described in the language specification.
As a result, it's possible to create extensions such as:
extension String {
var utf8data:NSData {
return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
}
}
However, what's the best naming practice for Swift source files containing such extensions?
In the past, the convention was to use extendedtype+categoryname.m for the Objective-C
type as discussed in the Objective-C guide. But the Swift example doesn't have a category name, and calling it String.swift doesn't seem appropriate.
So the question is: given the above String extension, what should the swift source file be called?
Most examples I have seen mimic the Objective-C approach. The example extension above would be:
String+UTF8Data.swift
The advantages are that the naming convention makes it easy to understand that it is an extension, and which Class is being extended.
The problem with using Extensions.swift or even StringExtensions.swift is that it's not possible to infer the purpose of the file by its name without looking at its contents.
Using xxxable.swift approach as used by Java works okay for protocols or extensions that only define methods. But again, the example above defines an attribute so that UTF8Dataable.swift doesn't make much grammatical sense.
I prefer having a + to underline the fact it contains extensions :
String+Extensions.swift
And if the file gets too big, you can then split it for each purpose :
String+UTF8Data.swift
String+Encrypt.swift
There is no Swift convention. Keep it simple:
StringExtensions.swift
I create one file for each class I'm extending. If you use a single file for all extensions, it will quickly become a jungle.
I prefer StringExtensions.swift until I added too much things to split the file into something like String+utf8Data.swift and String+Encrypt.swift.
One more thing, to combine similar files into one will make your building more faster. Refer to Optimizing-Swift-Build-Times
Rather than adding my comments all over the place, I'm surfacing them all here in one answer.
Personally, I take a hybrid approach that gives both good usability and clarity, while also not cluttering up the API surface area for the object that I'm extending.
For instance, anything that makes sense to be available to any string would go in StringExtensions.swift such as trimRight() and removeBlankLines().
However, if I had an extension function such as formatAsAccountNumber() it would not go in that file because 'Account Number' is not something that would naturally apply to any/all strings and only makes sense in the context of accounts. In that case, I would create a file called Strings+AccountFormatting.swift or maybe even Strings+CustomFormatting.swift with a formatAsAccountNumber() function if there are several types/ways to actually format it.
Actually, in that last example, I actively dissuade my team from using extensions like that in the first place, and would instead encourage something like AccountNumberFormatter.format(String) instead as that doesn't touch the String API surface area at all, as it shouldn't. The exception would be if you defined that extension in the same file where it's used, but then it wouldn't have it's own filename anyway.
If you have a team-agreed set of common and miscellaneous enhancements, lumping them together as an Extensions.swift works as Keep-It-Simple first level solution. However, as your complexity grows, or the extensions become more involved, a hierarchy is needed to encapsulate the complexity. In such circumstances I recommend the following practice with an example.
I had a class which talks to my back-end, called Server. It started to grow bigger to cover two different target apps. Some people like a large file but just logically split up with extensions. My preference is to keep each file relatively short so I chose the following solution. Server originally conformed to CloudAdapterProtocol and implemented all its methods. What I did was to turn the protocol into a hierarchy, by making it refer to subordinate protocols:
protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
var server: CloudServer {
get set
}
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void)
}
In Server.swift I have
import Foundation
import UIKit
import Alamofire
import AlamofireImage
class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void) {
.
.
}
Server.swift then just implements the core server API for setting the server and getting the API version. The real work is split into two files:
Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift
These implement the respective protocols.
It means you need to have import declarations in the other files (for Alamofire in this example) but its a clean solution in terms of segregating interfaces in my view.
I think this approach works equally well with externally specified classes as well as your own.
Why is this even a debate? Should I put all my sub classes into a file called _Subclasses.swift. I think not. Swift has module based name spacing. To extend a well known Swift class needs a file that is specific to its purpose. I could have a large team that creates a file that is UIViewExtensions.swift that express no purpose and will confuse developers and could be easily duplicated in the project which would not build. The Objective-C naming convention works fine and until Swift has real name spacing, it is the best way to go.
Say I defined a private function in a dart file hello.dart:
_hello() {
return "world";
}
I want to test it in another file mytest.dart:
library mytest;
import 'dart:unittest/unittest.dart';
main() {
test('test private functions', () {
expect(_hello(), equals("world"));
}
}
But unfortunately, the test code can't be compiled. But I do need to test that private _hello function. Is there any solution?
While I agree that private methods/classes shouldn't be part of your tests, the meta package does provide an #visibleForTesting attribute, and the analyzer will give you a warning if you attempt to use the member outside of its original library or a test. You can use it like this:
import 'package:meta/meta.dart';
#visibleForTesting
String hello() {
return "world";
}
Your tests will now be able to use it without error or warning, but if someone else tries to use it they'll get a warning.
Again, as to the wisdom of doing this is another question - usually if it's something worth testing, it's something that's worth being public (or it'll get tested through your public interfaces and that's what really matters anyway). At the same time, you might just want to have rigorous tests or test driven principles even for your private methods/classes so - Dart lets you this way.
Edit to add: If you're developing a library and your file with #visibleForTesting will be exported, you are essentially adding public API. Someone can consume that with the analyzer turned off (or just ignore the warning), and if you remove it later you may break them.
Several people believe we shouldn't test private directly: it should be tested through the public interface.
An advantage of following this guidance, is that your test won't depend on your implementation. Said differently: if you want to change your private without changing what you expose to the world, then you won't have to touch your tests.
According to this school of though, if your private is important enough to justify a unit test, then it might make sense to extract it in a new class.
Putting all this together, what you could do here, is:
Create a kind of helper class with this hello method as public. You can then easily unit test it
Let your current class use an instance of this helper class
Test the public methods of your current class which relies on _hello: if this private has a bug, it should be catch by those higher level tests
I don't like either of the above answers. dart's private variable test design is very bad. dart's private visibility is based on library, and each .dart file is a library by default, similar language is rust, but rust can write test code directly in the file, there is no private visibility problem, while dart does not allow this.
Again, I don't think #visibleForTesting is a valid solution,
Because #visibleForTesting can only be used to decorate public declarations, it serves as a mere analysis reminder that developers cannot invoke these declarations in other files,
But from a syntax point of view, developers can't use the _ prefix either, so the form, public, private, becomes confusing. and violates dart's own naming rules.
The argument that one should not test private, or that they should be separated into other classes, is like a justification that is completely unacceptable.
First, private exist because they belong to a business logic/model etc. in a contextual relationship, and it does not make logical sense to separate it into another class.
Second, if you must do this, it will greatly increase the complexity of the code, for example, you move to other classes will lose access to the context variables, or you have to pass a separate reference, or have to create an instance of the class, indeed, then you can finally do some mocks, but you also add a layer of abstraction,
It's hard to imagine that if you were to do this for the whole project, you'd probably double your entire code layers.
For now, If you want your dart package to get more than 90% coverage,
you should not define any private.
It sounds harsh, but that's the real story.
[Alternative] No one seems to have mentioned this yet,
Using part / part of to expose the privates, you can define a test-specific .dart file as the public interface to the library(file) to be tested, and use it to expose all the private declarations that need to be tested. you can name them xxx.fortest.dart
But this is more of a psychological solution, since you are still essentially exposing all private variables/methods
But at least, it's better than splitting class,
Also, if one day dart finally solves this problem, we can simply delete these .fortest.dart files.
A suggestion would be to NOT make methods/classes private but to move code, where you want to hide implementation details, to the lib/src folder.
This folder is considered private.
I found this approach on the fuchsia.dev page in this section under "Testing".
If you want to expose those private methods/classes, that are located in the src folder, to the public, you could export them inside your lib/main file.
I tried to import one of my libraries A (projects are libraries) into another library B and couldn't import code that was in the src folder of library A.
According to this StackOverflow answer it could still be possible to access the src folder from A in library B.
From the dart documentation
As you might expect, the library code lives under the lib directory and is public to other packages. You can create any hierarchy under lib, as needed. By convention, implementation code is placed under lib/src. Code under lib/src is considered private; other packages should never need to import src/.... To make APIs under lib/src public, you can export lib/src files from a file that’s directly under lib.
Is it possible to override the class file location of a framework class via classmap and autoloader? If yes, then how?
Example: I want to override Zend\Form\Fieldset, so that everywhere in the framework where Zend\Form\Fieldset is referenced, I want it to use my own class file instead of the original.
Motivation: When updating the framework, I want to keep my modifications safe from getting overwritten.
Known alternative: Modify the code in the framework.
Disadvantage: Modification gets lost when updating the framework.
writing the same class (FQCN) at another location is generally a bad idea. This causes two classes which are equally named to live in two separate locations. It's a much better idea to create your own Fielset in your own namespace. Say, Application\Form\Fieldset.
You can extend the ZF2 fieldset by your own. Then reference this new fieldset class and its all much more maintainable.
The downside of this method is you don't automatically use the new fieldset class. You have to reference the Application\Form namespace in every form you use. On the other hand, this makes it much more clear to other users of you code what exactly happens: there are no unexpected consequences using ZF2 code.
The only remark I have to make here is, for what do you need another fieldset? If you think you need that for view helpers, that's not true. You can modify the view helper to render fieldsets without modifying the Fieldset form class itself.
I am learning objective-C and I know we can use extension to add some private members to an interface.
But the book said there should be nothing in the ()
I read the following code snippet
#interface Tree(Private)
- (void)blah:(int)num;
#end
I am wondering why there is Private inside ()
You can put any name in the class category declaration, usually indicating the purpose of that category.
So in your case author of the code wanted to tell that those methods are for internal use of the class itself and are not intented to be called from other classes
The declaration in your example is precisely called a category (not an extension).
You can add as many categories as you like to any given Class (even if you don't have access to the source code). Categories allow you to add new methods to a class, but not new ivars nor properties. [1]
Each category has a name, which is the bit between parenthesis. There should not be two different categories for the same Class with the same name.
When the name is empty, this is called an extension. Extensions have some slight differences with categories: you can add ivars and properties to extensions and you can only use them for Classes for which you have access to the source code. [1]
Usually, extensions (like the example in your book) are declared at the top of the .m file, and are used for declaring methods, ivars and/or properties that are to be used only within that file (usually comprised of a single Class).
P.D.: If you really want to add new properties through categories as opposed to through extensions you can actually do so using associated objects [2][3].
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Defining a property in iOS class extension
http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/
In the case that is considered as a category, but since it's on the .m file, it will have the same effect. You can also see the tips from Xcode:
Being the mid one considered something like Tree(description) and the last one Tree ()
There are two closely related concepts here: class categories and class extensions. Class categories include a name inside the parenthesis and are most commonly used to add methods to existing classes or to organize methods into logical groups. Class extensions extend the internal implementation of the class (i.e. are used to define private properties, methods, etc).
More details can be found on Apple's dev site:
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html