I have an iOS app with some business logic. I would like to create an executable which would expose some calculations from the cli, so that I don't have to use the app.
Unfortunately, the code with the business logic that I want to expose depends on lots of other parts of the code, eventually pulling almost all the code. Even worse, it depends on some dependencies that are not available on macos (UIKit or DJISDK via pods).
I just want to write a main.swift, parse the arguments and use some functions from the codebase. What is the simplest way to do that ?
I don't mind if it's ugly (like pulling whole of UIKit in the executable) as long as it doesn't take to much time to implement.
I have two ideas:
remove all dependencies, optionally defining "dummy" classes compiled only for this target for some dependencies. That requires changing a lot of code, but seems to be cleaner.
find a way to pull the whole app in the new target. For example I have a UnitTests target which does that and can run on mac (though an app window appears when the tests run). But I have no idea how to do that.
Any help or guidance to good documentation would be greatly appreciated :)
I did my best to remove all unneeded dependencies, but there was a lot left that couldn't be removed easily. I resulted in using "dummy" classes to be able to compile without providing any logic.
Though it's not super elegant, it's a nice way to cut the dependency chain, and will let me remove the dependencies over time, while still being able to compile.
Ex:
// In common source file
class Business {
func usefulComputation() -> String {
...
}
func unneededFunction() -> UselessObject {
...
}
// In my CLI-target project
// file `DummyUselessObject.swift`
class UselessObject {
// add any function called from source file here, without putting any logic
}
// `main.swift`
let business = Business()
print(business.usefulComputation())
Related
Is it possible to distribute the code of a class to several files?
Honestly, I think the best route is to break it up into different roles that you compose into your class.
After all, how are you planning on breaking up your class?
Are you going to group methods and attributes according to similarity?
At that point you've just about come up with a role, so you might as well make it a role.
If you look at the source for Rakudo you see things like this:
class Perl6::Metamodel::ClassHOW
does Perl6::Metamodel::Naming
does Perl6::Metamodel::Documenting
does Perl6::Metamodel::LanguageRevision
does Perl6::Metamodel::Stashing
does Perl6::Metamodel::AttributeContainer
does Perl6::Metamodel::MethodContainer
does Perl6::Metamodel::PrivateMethodContainer
does Perl6::Metamodel::MultiMethodContainer
does Perl6::Metamodel::MetaMethodContainer
does Perl6::Metamodel::RoleContainer
does Perl6::Metamodel::MultipleInheritance
does Perl6::Metamodel::DefaultParent
does Perl6::Metamodel::C3MRO
does Perl6::Metamodel::MROBasedMethodDispatch
does Perl6::Metamodel::MROBasedTypeChecking
does Perl6::Metamodel::Trusting
does Perl6::Metamodel::BUILDPLAN
does Perl6::Metamodel::Mixins
does Perl6::Metamodel::ArrayType
does Perl6::Metamodel::BoolificationProtocol
does Perl6::Metamodel::REPRComposeProtocol
does Perl6::Metamodel::InvocationProtocol
does Perl6::Metamodel::ContainerSpecProtocol
does Perl6::Metamodel::Finalization
does Perl6::Metamodel::Concretization
does Perl6::Metamodel::ConcretizationCache
{
… # only 300 lines of code
}
If you do a good job of splitting up your roles, you should be able to use them in many classes.
How many classes in the Rakudo code base do you think compose in the Perl6::Metamodel::Naming role?
That role only provides a few things, and is only 45 lines long.
Here is an abbreviated version.
(All of the code in the methods has been deleted here for brevity.)
role Perl6::Metamodel::Naming {
has $!name;
has $!shortname;
method name($obj) {
…
}
method set_name($obj, $name) {
…
}
method shortname($obj) {
…
}
method set_shortname($obj, $shortname) {
…
}
}
Yes, there always is. But there us no standard supported way (yet anyway).
You can take the approach that Raku takes itself when creating the core settings: concatenate the files into a single file, and compile that. When you're building Rakudo from scratch, that's what's happening when you see the line:
+++ Generating gen/moar/foo
The generated files can be inspected in the gen/moar directory. At one point, I brought this up in a problem solving issue, but that never went anywhere. Perhaps that should be revisited.
You can use augment class. But that currently only makes sense inside a single file, because with multiple files it is creating multiple versions of the same "module" in pre-compilation. And the system is not able to determine what to resolve to what. This is when you realize that pre-compilation of Raku modules currently is creating libraries that need to be statically linkable at runtime.
My project i becoming messy because of the number of files, i need advices from devs.
For exemple i have string extensions, at start i was creating one per target. One for ios, one for watch OS etc ...
so I had something like :
extensionString.swift for iOS
extensionStrinWatchg.swift for watchOS
extensionStringTE.swift for today Extension
But with that method i got common code part between some targets and repeating code is never good, you agree.
So i started to make commun String extension files like
extensionStringIOS+watch.swift
extensionStringIOS+TD+watch.swift
extensionStringIOS+TD.swift
etc ...
adding to this the version that are only for a specific target we get :
extensionString.swift for ios
extensionStrinWatch.swift for watchOS
extensionStringTE.swift for today Extension
extensionStringIOS+watch.swift
extensionStringIOS+TD+watch.swift
extensionStringIOS+TD.swift
etc ...
You understand ... Thats a lot and that's messy. I loose time to find in which file to go
So now imagine this method for everything ...
The number of file become huge ...
I have that problem for extension, classes and others ...
So one file per target -> repeating code
second method : huge number of files, messy project and time wasting
So i have an idea but i'd like to know if it's the right way to do. What's the convention ?
My idea is to have one single extensionString.swift shared between all targets in my project and use things like this for code parts that shouldn't be used for all targets
#if !os(watchOS)
// do something
#else
// do something different
#if
So this applied in my project (not only extensions but class etc ..) could make me delete tons of files and regroup like this function for exemple :
/// boolean indicating if the user enabled the weekend days setting
static var isWeekendDaysSettingEnabled: Bool {
#if !os(watchOS)
if IS_ICLOUD_ENABLED {
return NSUbiquitousKeyValueStore.default.bool(forKey: KeyValueID.weekendDays.rawValue)
} else {
return UserDefaults.standard.bool(forKey: KeyValueID.weekendDays.rawValue)
}
#else
return UserDefaults.standard.bool(forKey: "weekendDays")
#endif
}
I think every answer here should start with big fat IMHO
There's no silver bullet and you have to decide which way to choose depending on your particular project.
As for me, I would try to separate all the logic into small frameworks, eg ExtensionsCrossplatform, ExtensionsIOS, ExtensionsWatchOS, etc.
An idea of having everything in one place is not so good and will lead to tight coupling between all the modules and platforms.
In fact, many big apps are comprised of big amount of tiny modules (more than 50).
Here's a video, which can describe the idea more https://badootech.badoo.com/the-immense-benefits-of-not-thinking-in-screens-6c311e3344a0
Now I have some experience in using the Zend Framework. I want to go deeper in the topic and rewrite some old php projects.
What is the best place to save own functions and classes?
And how do I tell Zend where they are? Or is there already a folder for own stuff? May I have different folders for different files?
For example I want to save a php document with the name math_b.php which includes several special functions to calculate and another one date_b.php which has abilities for datetime stuff. Is that possible or shall I have different files for every function?
I would also like to reuse the functions in other projects and then just copy the folders.
There is no single "right" answer for this. However, there are several general guidelines/principles that I commonly employ.
Do not pollute global scope
Namespace your code and keep all functions is classes. So, rather than:
function myFunction($x) {
// do stuff with $x and return a value
}
I would have:
namespace MyVendorName\SomeComponent;
class SomeUtils
{
public static function myFunction($x)
{
// do stuff with $x and return a value
}
}
Usage is then:
use MyVendorName\SomeComponent\SomeUtils;
$val = SomeUtils::myFunction($x);
Why bother with all this? Without this kind of namespacing, as you bring more code into your projects from other sources - and as you share/publish your code for others to consume in their projects - you will eventually encounter name conflicts between their functions/variables and yours. Good fences make good neighbors.
Use an autoloader
The old days of having tons of:
require '/path/to/class.php';
in your consumer code are long gone. A better approach is to tell PHP - typically during some bootstrap process - where to find the class MyVendor\MyComponent\MyClass. This process is called autoloading.
Most code these days conforms to the PSR-0/PSR-4 standard that maps name-spaced classnames to file-paths relative to a file root.
In ZF1, one typically adds the ./library folder to the PHP include_path in ./public/index.php and then add your vendor namespace into the autoloaderNameSpaces array in ./application/config.ini:
autoloaderNameSpaces[] = 'MyVendor';
and places a class like MyVendor\MyComponent\MyClass in the file:
./library/MyVendor/MyComponent/MyClass.php
You can then reference a class of the form MyVendor\MyComponent\MyClass simply with:
// At top of consuming file
use MyVendor\MyComponent\MyClass;
// In the consuming page/script/class.
$instance = new MyClass(); // instantiation
$val = MyClass::myStaticMethod(); // static method call
Determine the scope of usage
If I have functionality is required only for a particular class, then I keep that function as a method (or a collection of methods) in the class in which it is used.
If I have some functionality that will be consumed in multiple places in a single project, then I might break it out into a single class in my own library namespace, perhaps MyVendor.
If I think that a function/class will be consumed by multiple projects, then I break it out into its own project with its own repo (on Github, for example), make it accessible via Composer, optimally registering it with Packagist, and pay close attention to semantic versioning so that consumers of my package receive a stable and predictable product.
Copying folders from one project into another is do-able, of course, but it often runs into problems as you fix bugs, add functionality, and (sometimes) break backward-compatibility. That's why it is usually preferable to have those functions/classes in a separate, semantically-versioned project that serves as a single source-of-truth for that code.
Conclusion
Breaking functionality out into separate, namespaced classes that are autoloaded in a standard way gives plenty of "space" in which to develop custom functionality that is more easily consumed, more easily re-used, and more easily tested (a large topic for another time).
#import "whatever.h"
...wasn't perfect, but it was very handy for diagnosing circular dependencies, not to mention enforcing modularity.
You could be certain which classes knew about other classes--with the flick of a finger.
If you had to, you could comment out all the import statements, and add them back one at a time, in order to diagnose a dependency issue. It wasn't necessarily fast but it was dead simple.
And if a class didn't import anything other than the obligatory headers, Son, that's one modular class you had there!
If your project had ten classes that didn't import anything, then you knew that they were ten modular classes--you didn't have to package each class into its own Framework or anything like that. Easy.
But now, with Swift's policy of "everybody knows about everything all the time", it seems like it's just down to personal vigilance to sustain modularity. Personal vigilance is the worst kind!
Am I missing something? Is there a way to do these things easily in Swift?
If you want to modularize your Swift code, you should be using modules!
Creating a new module is pretty simple.
Add a new target to your project by clicking the plus sign here:
Select "Framework & Library" for the appropriate platform (iOS/OS X):
Choose "Cocoa Framework" (or Cocoa Touch, platform dependent) and click Next:
Give your module a name and change the language to Swift (or leave it as Objective-C, it doesn't matter, you can use both).
Add a Swift file to your module:
Add some code to your Swift file. Note, the default access level for Swift is internal which means it can be accessed from anywhere within the module but not from outside the module. Any code which we want to use outside the module must be given the public access level.
public class ModularSwift {
public init(){}
public var foo: Int = 0
}
Be sure to build your module (Cmd+B):
Go back to your original target, import the module and start using its code:
import MyModularSwiftCode
let foo = ModularSwift()
Xcode is perfectly happy:
Now, comment out the import statement and notice the errors:
I'm writing a small library which I'd like to be backwards compatible with older versions of an API, yet use features of the latest API when possible.
So for example, I have a project which uses an external API, which I'll call FooFoo_v1.
Initially, my code looked like this:
// in Widget.scala
val f = new Foo
f.bar
Foo has since released a new version of their API, FooFoo_v2, which adds the bat method. So long as I'm compiling against the new version, this works fine:
// in Widget.scala
val f = new Foo
f.bar
f.bat
But if you try to build against FooFoo_v1, the build obviously fails. Since the bat feature is truly optional, and I'd like to allow folks to build my code against FooFoo_v1 or FooFoo_v2.
Ignoring the details of the dependency management, what's the right high level approach for something like this? My aim is to keep it as simple as possible.
I think you should split your library in two pieces - one with features used from FooFoo_v1, another depending on the first one and on FooFoo_v2 and using features from FooFoo_v2. How to accomplish it depends on your code... If it's too difficult it's better to follow #rex-kerr advice - to maintain two branches.
I would simply keep separate branches of the project in a repository (one which is sufficiently robust to allow you to edit one and merge effortlessly into the others--git would be my first choice).
If you must do the selection at runtime, then you're limited to using reflection for any new methods.