Organizing extensions in Kotlin - swift

In Swift we usually use extensions as a way to organize methods in separate blocks and even files. This makes code much cleaner but it also allows us to do some tricks such as:
class API {}
extension API {
class Lists{}
}
extension Lists {
class Posts {
func latest() -> [Post] {
// get latest posts from a REST api
}
}
}
We can put any of the extension blocks in a separate file and it works perfectly in Swift.
Now one do the following to get the latest posts from the API in a clean way
let posts = API.Lists.Posts.latest()
Trying to convert that code into Kotlin I used SwiftKotlin converter tool that I thought that might work but it doesn't compile as It seems to be invalid:
class API {}
class API.Lists {}
class Lists.Posts {
companion object {
fun latest() {
// get posts
}
}
}
So I came up with the following that works fine and also compiles but it's not suitable for my case as methods can be quite long and I can't afford to have them all in one class in one file and I don't know how I can split them in multiple files.
class API {
class Lists {
class Posts {
companion object {
fun latest() {
}
}
}
}
}
Any suggestion is appreciated.

To put an extension on a companion object, you can write
fun API.Lists.Posts.Companion.latest() ...
You still need
class API {
class Lists {
class Posts {
companion object {
}
}
}
}
in a single file, but extensions can be defined elsewhere.

If you just want to mimic usage of these calls, you can use objects, like this for example:
object ApiPosts {
fun latest() {}
}
object ApiLists {
val Posts = ApiPosts
}
object API {
val Lists = ApiLists
}
API.Lists.Posts.latest()
But this is really not a Kotlin way, and in common case it's a bad practice to write in a language the way it's not supposed to.

One possible solution is to just extend the inner classes with normal functions not static ones (companion):
class ParentClass {
class InnerClass {
}
}
And in any other file you could do:
fun ParentClass.InnerClass.instanceMember() {
}
And for usage:
ParentClass.InnerClass().instanceMember()
Of course this isn't exactly like the Swift version but it's close enough.

Related

Objects with application-wide scope in Swift Vapor

How can I create objects within a Vapor-Applicaton that are instantiated when the app starts and are acessible from within my controllers?
I would like to use Dictionary to store some of my models across multiple requests and assign them to a user via hidden fields.
Unfortunately SessionData only accepts Strings.
Many thanks in advance
Michael
The obvious way is to extend Application. I used the documentation for Repositories as inspiration. First, create a structure to hold your properties:
struct AppConfig {
var emailStatus: EmailStatus
static var environment: AppConfig {
return .init(emailStatus: .unknown)
}
}
Then extend:
extension Application {
struct AppConfigKey: StorageKey {
typealias Value = AppConfig
}
var config: AppConfig {
get {
storage[AppConfigKey.self] ?? .environment
}
set {
storage[AppConfigKey.self] = newValue
}
}
}
Finally, initialise in configure.swift:
app.config.emailStatus = .unknown
I’ve used an enumeration as an example but it can be whatever you want.
Edit: Addressing OP's issues and concerns
I put the above code in a separate source file, so you need:
import Vapor
To gain access to StorageKey, etc.
Accessing the running application instance in a controller is easy, it's available from the request as in request.application.

How to define a class that is exactly the same as another class in Dart/Flutter

I'm defining some custom Exceptions in Dart.
I want in my logic to check the type of exception and base my processing on that, so I want to create distinct classes for each, for example like this :
class FailedToLoadCriticalDataException implements Exception { } // app cannot continue
class FailedToLoadNonCriticalDataException implements Exception { } // app can continue
However I also want to pass 2 parameters when I create these types of exceptions, the type of API call, and the API url, and the definition for that would look like this :
class UrlCallFailedException implements Exception {
String _dataTypeName;
String _urlEndpoint;
UrlCallFailedException([this._dataTypeName, this._urlEndpoint]);
#override
String toString() {
return "(${this.runtimeType.toString()}) Failed to fetch $_dataTypeName ($_urlEndpoint)";
}
}
Now what I want to do is (replace the initial definitions I made earlier and re)define my FailedToLoadCriticalDataException and FailedToLoadNonCriticalDataException classes so that they are exactly the code that is in the UrlCallFailedException class.
Is there any way to simply say something like class FailedToLoadCriticalDataException **is** UrlCallFailedException; and not need to duplicate the code that defines UrlCallFailedException ?
class FailedToLoadCriticalDataException implements UrlCallFailedException{ } is wrong because it is "Missing concrete implementations of 'getter UrlCallFailedException._dataTypeName',.."
class FailedToLoadCriticalDataException extends UrlCallFailedException{ } is wrong because when I got to throw FailedToLoadNonCriticalDataException("Foo", url); it's expectation is that there are no params ("Too many positional arguments: 0 expected, but 2 found.").
Is there a way to create multiple classes that behave exactly the same as another type and differ only in their class, without duplicating all the code ?
I've come up with this as a decent compromise :
class FailedToLoadCriticalDataException extends UrlCallFailedException {
FailedToLoadCriticalDataException([dataTypeName, urlEndpoint]) {
super._dataTypeName = dataTypeName;
super._urlEndpoint = urlEndpoint;
}
}
class FailedToLoadNonCriticalDataException extends UrlCallFailedException {
FailedToLoadNonCriticalDataException([dataTypeName, urlEndpoint]) {
super._dataTypeName = dataTypeName;
super._urlEndpoint = urlEndpoint;
}
}
Some, but minimal, code duplication, and I can now call throw FailedToLoadNonCriticalDataException("Foo", url); in my code later.

Best practices in protractor for big pageObject files

In my previous protractor JS project (This new one I will do it with TS) I created one class for all my elements and another one for my functions, something like this:
specs
|_reportPage
|_lib
|_pageElements.js
|_pageFunctions.js
Then I was importing the files as necessary, in this way was easy to find the info since the element list was long.
So far all examples online for protractor TS projects are short pageObject files with a couple of elements and methods, but I would like to know how to correctly proceed when the page requires a lot of elements and functions/methods.
For example, lets say we have 5 specs under the same folder that test the same page and this page is full of fields and tables.
What would be the best practice here? create 1 pageobject for each spec, create one long class with all the elements and functions...?
Thanks for your time!
To Extend my answer you can add additional layer as a service which can execute several actions from the flow in different pages.
Code example:
export class E2EService {
mainPage: MainPage = new MainPage();
innerPage: InnerPage = new InnerPage();
doSomethingE2E() {
this.mainPage.headerPage.weDoSomething();
this.mainPage.contentPage.weDoSomething()
this.innerPage.somethingComplicated();
}
}
export class MainPage {
public readonly headerPage: HeaderPage;
public readonly contentPage: ContentPage;
}
export class InnerPage {
headerPage: InnerHeaderPage;
contentPage: InnerContentPage;
public somethingComplicated() {
this.headerPage.weDoSomething();
this.contentPage.weDoSomething();
}
}
export class ContentPage {
private readonly elements = {
// elements
};
public weDoSomething() {
// code
}
public getElements() {
return this.elements;
}
}
export class HeaderPage {
private readonly elements = {
btn1: element(by.id('')),
div: element(by.id('')),
h2: element(by.id(''))
};
public weDoSomething() {
// code
}
public getElements() {
return this.elements;
}
}
Based on Infern0's answer, I did dependency injection to the classes:
class HeaderElements {
foo = element(by.id("foo"));
//List goes on...
}
class HomePageElements {
foo = element(by.id("foo"));
//List goes on...
}
export class MainCommonElementsPage {
headerElements: HeaderElements;
homePageElements: HomePageElements;
constructor() {
this.headerElements = new HeaderElements();
this.homePageElements = new HomePageElements();
}
}
Best practices, even for large Page Objects is this:
Each page should only have 1 page object class. All of the tools needed to access that page should be located here. Think of your page object as an API.
Don't break the PO into different parts, especially for large pages. You'll eventually need to modify the PO to adjust for content changes. Would you rather change 1 file or 12? This also ensures that each of your e2e tests will remain functional after you update the PO.
I have one PO that handles a page with a lengthy form. The form has 12 controls and three buttons (cancel, reset, and submit). I have about 30 functions that deal with the form. I don't like having more than 1-2 methods in my test, so if it gets more complicated, I add to the PO.

How to efficiently reuse Ionic page against different providers?

I'm working with Ionic 2 and I have entity management page which is suitable for different data providers.
Now I have page for character management.
export class CharacterListPage{
currentItems: Character[];
constructor(public provider: Characters) {
this.currentItems = this.provider.query();
}
// other stuff
}
I need to do creature management. Creatures structure is identical to character structure.
Obvious way is just copy-paste page and make some renaming:
export class CreatureListPage{
currentItems: Character[];
constructor(public provider: Creatures) {
this.currentItems = this.provider.query();
}
// other stuff
}
Is it possible to use more efficient way?
That looks like a typical use case for an abstract class, luckily typescript brings that feature to the .js world:
You have a base class, lets call it ListPage, which holds all the common functionality of a Character and a Creature which can then be extended by other pages and reuse this existing functionality:
class ListPage {
listItems: Character[] | Creature[];
constructor(provider: Characters | Creatures) {
this.listItems = provider.query();
}
// other common methods
}
class CharacterListPage extends ListPage {
constructor(provider: Characters) {
super(provider);
}
}
class CreatureListPage extends ListPage {
constructor(provider: Creatures) {
super(provider);
}
}
For this minimal example it may not seem very efficient but when your classes get more complex and have much common functionality it will be very useful.
Here you can find the documentation on typescript classes.

Actionscript in a single class or in multiple scenes?

I am completely new to Actionscript and Adobe Flash CS6 and for a little bit of fun I have decided to try and make a little game. I had a few newbie (or noob-y) questions to ask about a general implementation approach.
The documentation I've been reading so far suggests creating a new flash project, and then create a document class so:
package {
import flash.display.MovieClip;
public class MyMainClass extends MovieClip {
public function MyMainClass() {
}
}
}
and I am wondering if I use this MainClass to code the whole game or include actionscript within a scene and have multiple scenes, or some combination of both.
Lets say I had a wanted 5 Levels in my game, would I do something like:
package {
import flash.display.MovieClip;
public class MyMainClass extends MovieClip {
public function MyMainClass() {
StartLevel1();
StartLevel2();
StartLevel3();
StartLevel4();
StartLevel5();
}
public function StartLevel1() {
// Do something
}
public function StartLevel2() {
// Do something
}
public function StartLevel3() {
// Do something
}
public function StartLevel4() {
// Do something
}
public function StartLevel5() {
// Do something
}
}
}
or create 5 scenes with actionscript in each scene?
Can anyone provide me with a bit of a starting point?
Thanks
I don't know of anyone who has anything good to say about scenes.
However, as you intuit, the timeline itself is a wonderful tool for managing the state of your Flash assets over time. If you use it, you also get the hidden advantage that you don't have to download 100% of your file to be able to use it (so you can reduce or even eliminate the need for a preloader by unchecking "Export in frame N" on your library symbols.
Lars has quite rightly pointed out that there are very few developers who understand this technique, and I know of exactly one who can and will help people who are interested in exploring this technique. That person is helping you right now. So if you choose to go that way, keep in mind you are mostly on your own except if I happen to notice your post and respond to it.
I am not in favor of timeline scripts, with a very few exceptions. What I suggest is a "both and" approach, where you use a Document Class to control timeline instances.
Your document Class might look something like this:
public class Game extends MovieClip {
protected var _level:ILevel;//Interface your Level MovieClips will implement
protected var levelController:LevelController = new LevelControler();
protected var currentLevel:int;
protected var maxLevels:int = 5;
public function Game() {
levelController.addEventListener(LevelEventKind.LEVEL_COMPLETE, nextLevel);
levelController.addEventListener(LevelEventKind.LEVEL_FAILED, gameOver);
startLevel(currentLevel);
}
public function startLevel(levelNumber:int):void {
goToLabel('Level' + String(levelNumber));
}
public function get level():ILevel {
return _level;
}
public function set level(value:ILevel):void {
_level = value;
//internally, this should release all listeners to the last
//level object (if any) so you don't get a memory leak
levelController.level = _level;
}
protected function nextLevel(e:Event):void {
if (currentLevel < maxLevels) {
startLevel(++currentLevel);
} else {
//do you won logic here
}
}
protected function gameOver(e:Event):void {
//do bombed out logic here
}
protected function goToLabel(label:String):void {
for each (var frameLabel:FrameLabel in currentLabels) {
if (frameLabel.name==label) {
//if your swf is media-heavy, may want to check that frame
//is loaded if you chose to reduce/eliminate preloader
goToAndStop(label);
return;
}
}
trace('no such label as', label);
}
}
What this gets you is a game where you can change how the different levels look without changing a single line of ActionScript, and you can change how they work by assigning different Base Classes that implement ILevel slightly differently. You can also change your functionality by swapping out different flavors of LevelController, but your Main Document Class (Game in this instance) would be aware of this change (wheras the other changes could be made without altering Game at all).