GithubHelp home page GithubHelp logo

hmlongco / factory Goto Github PK

View Code? Open in Web Editor NEW
1.7K 1.7K 107.0 3.89 MB

A new approach to Container-Based Dependency Injection for Swift and SwiftUI.

License: MIT License

Swift 99.15% Objective-C 0.39% Ruby 0.35% Shell 0.10%
container dependency-injection ios swift swiftui xcode

factory's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

factory's Issues

Resolvers .implements?

Hello Mr. Long,

i love the work you did with Resolver and now Factory and am trying to refactor my project.
I stumbled into one problem that Resolver solved for me.

Resolvers:
@discardableResult public func implements<Protocol>(_ type: Protocol.Type, name: Resolver.Name? = nil) -> ResolverOptions<Service> { registration.resolver?.register(type.self, name: name) { r, args in r.resolve(Service.self, args: args) as? Protocol } return self }

is missing on Factory and plays a huge part of our architecture which is sliced into several frameworks that need to use the same object based on their own protocol implementations.

E.g.
register  { AuthenticationClass() }.implements(AuthenticationProtocol.self).implements(LoginProtocol.self)

Where “AuthenticationProtocol” sits on another framework as “LoginProtocol”.

I didn’t find a solution for Factory that would serve us without exhibiting the real “AuthenticationClass” to both of them yet.

Greetings Michael S.

What is best way to DI in this situation?

Hello. i'm newbie in factory
now I'm trying to put factory in my project
but i'm little hard to construct DI Architecture
So.. can i get some advice on this?

----------- MY SITUATION --------------
E.x) before (factory)
if i create new viewController instance ..

 let myRecordViewController = MyRecordViewController(viewModel: MyRecordViewModel(usecase: RecordsUseCase(recordsRepository: RecordsRepositoryImpl(recordAPI: RecordAPI()))))

--> my core VC count is 5 (home, record, search, dj, profile)
E.x) after (add factory)
so.. now i'm trying ..

import Factory
import Alamofire

extension SharedContainer {
    static let defaultSession = Session.default
}

seperate container (home, record, search, dj, profile) like this

class RecordContainer: SharedContainer {
    static let recordVC = Factory<MyRecordViewController> {
        MyRecordViewController(viewModel: MyRecordViewModel(usecase: RecordsUseCase(recordsRepository: RecordsRepositoryImpl(recordAPI: RecordAPI(session: defaultSession)))))
    }
}

What is best way to Di in this situation?
Am I going the right way?
Thank you!

Equivalent of Resolver's @InjectedObject ?

Hi Michael!
Nice to see that new Factory project! I am a big fan of Resolver. I am trying to migrate from Resolver to Factory, and I was wondering how to inject an ObservableObject as a StateObject in a View, like it was possible in Resolver...
Do you still support this use case?

I can't register new instance

Hi @hmlongco
I'm big fan of Factory
but i face some problem now (title)
It would really help me if I could take your advice.

My situation is ..

-- Container --

extension Container {
    static var notificationUsecase = Factory<ReserveNotificationUsecase> { ReserveService() }
}


extension Container {
    static func setupMocks() {
        notificationUsecase.register(factory: { ReserveStubService() })
    }
}

-- ViewModel --

extension ReserveViewModel {
 struct Dependency {
        @Injected(Container.notificationUsecase) var notificationUsecase
    }

    private func viewModelSomeFunc() {  // this is called after init() 3 seconds
        Container.setupMocks() // <- register Stub here!! but .. 
        LogUtil.d(dependency.notificationUsecase) // ReserveService   <--- WRONG <---- (I want this part is defined as ReserveStubService )
        LogUtil.d(Container.notificationUsecase.callAsFunction()) // ReserveStubService <--- OK 
}

@injected Instance != Container Instance

I tried for five hours, but it didn't work..
https://github.com/hmlongco/Builder
I also tried to refer to this demo app, but it failed
What did I miss?

++)
-- my debugging range --
Screen Shot 2022-10-08 at 6 00 03 PM

I don't know where to go from here.
Thanks

CocoaPods

Are you planning in making the lib available using cocoapods?

Can't install Factory over Cocoapods for WatchOS Target

When I add the Factory-Package to my Podfile and run pod install i get following message:

Analyzing dependencies
[!] The platform of the target `Watch App` (watchOS 9.1) is not compatible with `Factory (1.3.5)`, which does not support `watchOS`.

This is the podfile:

# Uncomment the next line to define a global platform for your project
platform :ios, '12.0'

target 'Watch App' do
  platform :watchos, '9.1'
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'Factory', '~> 1.3.5'

Am I doing something wrong?

The Package.Swift-File for the Swift Package Manager states that .watchOS(.v6) is also supported.

Best regards

Holger

Service-Locator Example with Tuist

Hello @hmlongco,

I've read the majority of your articles and looked for an idea for Compile-Time safety Dependency Injection Library. The API and usage from SwiftUI inspired usage is a brilliant idea!!

I have written an article about Composition Root and Service Locator patterns by using Swinject and your library on Tuist's uFeature Architecture idea.
The modular strategy in my article is inspired by Bruno Rocha from Spotify.
I have used some of your lastly updated APIs to follow the strategy. My article can be wrong since I have no experience.
If you find my idea and article beneficial, I would be really happy if it is mentioned in the Additional Resources Part of the Project's Readme file or any other places. I am open to any of your feedback about the article.

Medium -> Link
Project branches(Factory, Factory-Finished) -> Link

Multi-Module / Visibility

When using multiple modules and only having protocols (and not concrete implementations) available, the compile-time safety of factory cannot be sustained.

We have a package "Domain" which has access to a UserRepositoryProtocol. Another package "Data" contains the UserRepository implementation. Data depends on Domain.
When defining the DI-Container in Domain, we have to use

public static var userRepositoryFactory: Factory<UserRepositoryProtocol>!

And in Data

DomainContainer.userRepositoryFactory = DataContainer.userRepository

Is this the suggested solution for multi module projects?

1.3.5 Is Not Available

This is not a significant issue. Nonetheless, we can not get version 1.3.5 using Cocoapods. The podspec is updated, but the version might not have been published.

Perhaps a GitHub Action for when a new tag is pushed would be helpful to avoid doing this repetitive job every time.

Cached vs Singleton scope, what's the difference?

Hello.
I'm having a hard time understanding the difference between the cached and singleton scopes.
Both will keep one instance of an object in memory and return that instance to the caller and both scopes have the reset functionality (Scope.cached.reset() and Scope.singleton.reset()).
Which leaves me a bit confused about the differences between the two.

Reset session

Hi,

I'm trying to reset a cached registration using the .session example for a user account that is obtained via MSAL. When I try to reset it in my logout handler the state isn't being updated in my swift ui Auth view. Am I doing something wrong? The view is using an EnvironmentObject for reference.

Cheers

Simon

Workspace and clean architecture setup

Hi, I am not able to wrap my head around how to best use Factory in a multi-project setup, formed around a clean architecture pattern. This was easy with Resolver, but in Factory it seems to lead to circular references - unless you accept a "doubling" of references.

Consider the following architecture in an XCWorkspace:

App (contains the SwiftUI project with views and viewmodels)
Core (framework that contains the protocols and models)
Services (framework that contains the services, for example external api integrations)
Bootstrap (framework that bootstraps Services and Core for dependency injection/ioc)

In Factory, registrations made in Bootstrap will not be visible to App or Services.

In a clean architecture using xcworkspace, separation is the key benefit. App should not know about the concrete implementations of the services, it will only operate on the protocols. Therefore, App does not have a reference to Services, only to Core where the protocols live. And because of that, a separate project needs to do the bootstrapping, ie Bootstrap.

My Bootstrap project contains only this, and embeds the Core and Services projects to make this work:

extension SharedContainer {
static let httpClient = Factory(scope: .singleton) { HttpClient() as HttpClientProtocol }
static let linksService = Factory(scope: .singleton) { LinksService() as LinksServiceProtocol }
}

My App project embeds the Bootstrap project and the Core project

My Services project embeds Core.

Services needs an instance of HttpClientProtocol: @injected(Container.httpClient) private var httpClient: HttpClientProtocol

But that will not work, since the registration is done in Bootstrap. Services has no notion of Bootstrap at all.

Is there a way with Factory? If not, the Inversion of Control part of Dependency Injection is missing in this framework, and it will only work for monolith projects.

Determine scope for optional registration

I would like to use injection among modules. Let's say a module depends on other module's interface module which contains protocol definition. Beside that interface I would like to place the factory of the optional type as well.
In this case how can I define the scope at the explicit register() call for example in a third (main) module where only that module should know about the lifecycle? So the scope definition could remain always at the place of the actual registration.

Resetting cached scope doesn't update @Injected var instance

Problem

When using the @Injected property wrapper to reference a service, the @Injected var always references the initial instance of the service even after resetting the scope tied to the service.

For example, I created a custom scope called session of type Cached and a TestService that is registered with the session scope. When Container.Scope.session.reset() is called, the @Injected var never updates to the new instance, but when referencing the service directly via Container.testService(), it returns the new instance.

Example Project

See the attached example project and screen recording.

In the project, there is a class called TestService that simply has an id variable associated to it. This class gets registered as a Factory with the custom scope of session.

Every second via a repeating timer, the project prints out testService.id (which is an @Injected var) and Container.testService().id in the console.

Pressing the "Reset Session Scope" button calls Container.Scope.session.reset().

After pressing the button, notice how the testService.id (the @Injected var) continues to print out the old/initial id in the console while the Container.testService().id prints out the new id.


I assume the expected behavior is for the initial/old instance of TestService be deallocated and the new service be returned everywhere including via an @Injected var.
This seems to be an issue to me unless I am missing something.
I appreciate the help - thanks.


Example Xcode Project: XcodeTestProject.zip

Screen Recording:
reset_factory_cache_bug_sample_project

Shared scope tests failed under iOS 13.7

v1.2.9

When run unit tests using iOS 13.7, the tests testProtocolSharedScope and testExplicitProtocolSharedScope fails. The same functions pass with success with iOS 15 .

Both fails when running this assert function: XCTAssertTrue(service1?.id == service2?.id)

I think it will always create a new instance when using iOS 13, even using shared scope.

[Need help]Container not picking mock object in Unit Tests

Hi I am using latest factory version. I followed the doc. I tried to override my objects for test. It always invoke real object.

My container looks as below:

extension Container {
    var blogPostRepository: Factory<BlogPostsRepository> { self { BlogPostsRepositoryImpl(apiClient: self.apiClient.resolve()) } }
}
extension Container {
    
    var blogListViewModel: Factory<BlogListViewModel> {
        Factory(self) {
            BlogListViewModel(repository: self.blogPostRepository.resolve(), mainScheduler: self.mainScheduler.resolve())
        }
    }
}

extension Container {
    var apiClient: Factory<APIClient> {
        self { RESTAPIClient(url: URL(string: "https://jsonplaceholder.typicode.com/posts/")!) }
    }
}

extension Container {
    var mainScheduler: Factory<AnyScheduler<DispatchQueue.SchedulerTimeType, DispatchQueue.SchedulerOptions>> {
        Factory(self) {
            .main
        }
    }
}

I have used KIF-framework to write a test. I have debugged the code. Container always invoking real object not mock object.
I have pushed the mock to container in setup and popped in tearDown however result remains same.

func testExample() throws  {
        let repository = BlogPostMockRepository()
        repository.response = MockResponse(body: blogPosts, error: nil)
        mockBlogRepository = repository
        Container.shared.blogPostRepository.register { repository }
        Container.shared.mainScheduler.register { .immediate }
        
        let tableView = tester().waitForView(withAccessibilityIdentifier: "blogPostTableView") as! UITableView
        XCTAssertEqual(tableView.numberOfSections, 1)
        XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1)
 }

Question about Dynamic Registration example

func authenticated(with user: User) {
    ...
    Container.userProviding.register { UserProvider(user: user) }
    ...
}

In the above example that you provide, what was the way that userProviding was initially registered? Should this be created as a nilable, a UserProvider that takes no user, or even a separate type conforming to UserProviding protocol?

Graph Scope

First of all, I would like to thank for this library. It's exactly what we were looking for.

I was wondering why Factory does not have built-in GraphScope. I know that Resolver had that kind of functionality so I am wondering about reasons why it's not included here. I think it's possible implement it in this way:

func mapInGraph<T>(_ resolve: (GraphIdentifier) -> T) -> T {
            // Will create new graph id if it is the root
            // Otherwise it will use graphID from parent graph
            let isRoot: Bool = Self.graphID == nil
            let graphID = Self.graphID ?? UUID()

            if isRoot {
                Self.graphID = graphID
            }

            // Resolve instance
            let instance = resolve(graphID)

            if isRoot {
                // reset graph ID when exiting the graph
                Self.graphID = nil
            }
            return instance
        }

cache would be then per graph:

private var cache: [GraphIdentifier: [Identifier: any Box]] = .init(minimumCapacity: 64)

and then resolve function has to be changed:

func resolve<T>(id: Identifier, factory: () -> T) -> T {
            defer { lock.unlock() }
            lock.lock()

            return mapInGraph { graphID in
                /// retrieve from cache based on graphID
                /// ...

                /// if not find in cache create new instance and store in cache based on grapID
                /// ...
            }
        }

There's some trickery that needs to be implemented because of multithreading but this is the basic concept. Do you see any problem with it?

[Question] What's the best practice to use Factory in a multi-modules project?

First, thanks for releasing awesome DI library. 👍
I have one question.
I thought as below, but this way seems to have some disadvantages of always having to specify the type as optional since it cannot give an initial value.
If you have feature modules, what do you think is the best way to inject dependencies into each module?

In a feature module,

class AFeatureContainer: SharedContainer {
    static let optionalService = Factory<ServiceType?> { nil }
}

In a main module,

AFeatureContainer.optionalService.register { Service() }

[Question] - Migration from Resolver

Hi Michael,

great to see another dependency injection library from you. I am a long time Resolver user and now questioning myself if it is possible to migrate from Resolver to Factory and how. I hope it is fine to ask some question about this in this format.

Currently Resolver is used in a MicroFeature architecture. So I have a lot of distinct features, all with an interface target and an implementation target. These features then are getting packed together in the final application target.

Each feature implementation only knows the interface of other features AND the Resolver framework. The application target in the end knows each features interface and each features implementation and registers appropriate implementations to the interfaces for other features to consume.

Some Code examples below.
Feature A

// FeatureA interface

protocol FeatureAInterface {
    func fetchResourceA() async -> ResourceA
}
// FeatureA implementation

protocol FeatureAImplementation: FeatureAInterface {
    func fetchResourceA() async -> ResourceA {
        return ResourceA()
    }
}

Feature B

// FeatureB interface

protocol FeatureBInterface {
    func fetchResourceB() async -> ResourceB
}
// FeatureB implementation

final class FeatureBImplementation: FeatureBInterface {
    
    @Injected private var featureA: FeatureAInterface   
    
    func fetchResourceB() async -> ResourceA {
        let a = await featureA.fetchResourceA() 
        return ResourceB()
    }
}

App

import FeatureA
import FeatureAInterface

import FeatureB
import FeatureBInterface

register { FeatureAImplementation() }
    .implements(FeatureAInterface.self)

register { FeatureBImplementation() }
    .implements(FeatureBInterface.self)

When I now look at Factory I saw that it is now required to create an extension on Container to make services explicitly type safe available to consumers. Maybe I misunderstood the new library a little bit, but do you have some suggestion of how the behaviour I described will be working with Factory ? What I want to avoid is to expose the implementation of features to other features. Exposing implementations inside the place where everything is registered is fine though.

Maybe another question - will it also be possible to have a @OptionalInjected functionality again ? Maybe I oversaw it.

Thanks a lot in advance, and again thanks a lot for all your work so far !

Question about scopes in different containers

Hello I have a problem with scopes of some services which I want share between containers as singletons. The service created as many times as it injects by different containers.
In the next example sharedService inits twice when MyConstructedService is created and when sharedService injected by something else. What I need: only one sharedService ever. How I can do that?

extension SharedContainer {
    var sharedService: Factory<MyServiceType> { self { MyService() }.singleton }
}

final class DemoContainer: ObservableObject, SharedContainer {
    static var shared = DemoContainer()

    var constructedService: Factory<MyConstructedService> {
        self {
            MyConstructedService(service: sharedService())
        }
    }

    var manager = ContainerManager()
}

Thank you

Blocked Threads

👋
Sorry if my knowledge about NSLock isn't that extensive, but since calling a lock twice can permanently block a thread, is it not a bit dangerous to use it? Specially if called on main thread.

If I create a Factory and immediately execute a function inside that new object, it will lock the thread permanently since it's locking the thread twice. Try this SomeContainer.myService().executeSomeMehtodInsideService(). The factory is registered as .singleton.

I did check and the NSLock instance is exactly the same. On the Scope.resolve(id:factory:) it's locking the thread on line 197 and locking again on line 207, because eis using the same instance of NSLock.

So would it make it safer to use the NSRecursiveLock? Allowing for this behaviours without changing how the code works?

LMK if I'm doing something wrong or Is this an issue.

Container or SharedContainer

Hello Sir,

I have a simple question about the Container class, because I didn't understand what is the real interest of this one ?

We can already use SharedContainer or we can create our own container with the SharedContainer inheritance. Both make definitely sense.

Then I opened the Factory.swift:
public class Container: SharedContainer { }

So why did you create this Container class ? What is the difference with create our own container ?
I supposed it just a default container for user. Is it right ?

Thanks,
Paul

Crash when using singleton

I have found a SIGABRT error occurs under a specific scenario. In this case, I am trying to provide a protocol for UIApplication, and I am setting this as a singleton (this is so that I can provide a mock during testing). The issue appears to be caused when setting the scope as singleton, and the factory itself is a singleton. I am providing the code here which causes the issue. All you need to do is run the test.
FactoryDemo.zip

Optional injected services don't get new instance after register

Hello, I have an optional service

static let serviceA = Factory<serviceAProtocol?>(scope: .singleton) { nil }

In my classA I have a code like this

@Injected(Container.serviceA) private var serviceA

Then I call register for this service in classB, after registration I need to call a func of serviceA in classA but in this class serviceA always nil. I think it is not an expected behaviour, @Injected should take new instance instead of nil.

I think my case is similar to #35 but optional services expected to be replaced after registration. Thank you.

SharedContainer Resolve

Hey @hmlongco! I was thinking in a way to resolve a Factory passing a type something like that:

open class SharedContainer {

    public static func resolve<T>(scope: Scope) -> T? {
        resolveRegistration() ?? resolveScope(scope: scope)
    }
    
    static func resolveRegistration<T>() -> T? {
        let factories: [T] = Container.Registrations.registrations.compactMap { key, factory in
            guard let currentFactory: T = (SharedContainer.Registrations.factory(for: key) as? TypedFactory<Void, T>)?.factory(()) else {
                return nil
            }
            return currentFactory
        }
        return factories.first
    }
    
    static func resolveScope<T>(scope: Scope) -> T? {
        scope.cache.compactMap { id, factory in
            factory.instance as? T
        }.first
    }
 }

Do you think that this could be a way to do that? Or im not thinking in something?

Scope not working as expected

Hello,

First of all, great job on creating this library! 👍🏻

Description

I might be misunderstanding the functionality of scope, so I apologize upfront if that is the case.

  • I was following the provided sample code from the README.md, but I wasn't able to get it to work for my use case.
  • Specifically, I have the following:
extension Container.Scope {
    static var session = Cached()
    static var loggedOut = Cached()
}

extension Container {
    // Used to send requests.
    static let httpProvider = Factory(scope: .shared) { HttpProvider(...) }
  
    // Services available when the user is logged out:
    static let authService = Factory<AuthService>(scope: .loggedOut) { AuthServiceImpl(provider: httpProvider()) }

    // Services available when the user is logged in:
    static let userProvidingService = Factory<UserProvidingService>(scope: .session) { UserProvidingServiceImpl(provider: httpProvider()) }
    static let logoutService = Factory<LogoutService>(scope: .session) { LogoutServiceImpl(provider: httpProvider()) }
}

public final class AuthServiceImpl: AuthService {
    // From AuthService protocol
    public func login() async throws {
        // I do not want `authService` to be available after successful login.
        defer { Container.Scope.loggedOut.reset() }
        
        // Receives successful login request ...
    }
}

public final class LogoutServiceImpl: LogoutService {
    public func logout() async throws {
        defer {
            Container.Scope.session.reset()
            Container.authService.register { AuthServiceImpl(provider: Container.httpProvider()) }
        }
        // Successfully logout the user ...
    }
}

And these are used in the appropriate ViewModel:

public struct LoginViewModel: ObservableObject {
    @Injected(Container.authService) private var authService

    public func login() async throws {
        try await authService.login()
    }
}

public struct ProfileViewModel: ObservableObject {
    @Injected(Container.userProvidingService) private var userProvidingService
    @Injected(Container.logoutService) private var logoutService

    public func logout() async throws {
        try await logoutService.logout()
    }
}
  • Then I tried testing using authService when it really shouldn't be available (after login)
public struct ProfileViewModel: ObservableObject {
    // ...
    @Injected(Container.authService) private var authService

    // ...

    #warning("TEST: REMOVE")
    public func test() async throws {
        try await authService.login() // I expected this to throw some kind of error, but instead it fired a request.
    }
}

When I did the same thing in an unsafe manner everything worked as expected (ie: the services were nil when they were not needed)

Am I missing something here? Is what happens inside the test() function expected behaviour?

Equivalent for Resolver's Names

Suppose that I have this protocol in a swift package

public protocol ErrorMapper {
    func map(responseError: AFError, responseData: Data?) -> Error
}

which will be exposed like this externally

public extension Container {
    static let errorMapper = Factory<ErrorMapper?> { nil }
}

This protocol will have two different implementations in the main project.

struct LoginErrorMapper: ErrorMapper {}
struct UsersErrorMapper: ErrorMapper {}

How do I register those? With Resolver there was something like:

register(name: .loginError) { LoginErrorMapper() as ModuleA.ErrorMapper }
register(name: .usersError) { UsersErrorMapper() as ModuleA.ErrorMapper }

Support for Async/Await Concurrency in Factory

Hey @hmlongco,

First of all would like to say well done on creating both Resolver and Factory. I have been using Resolver in production for over a year now and really happy on how much it helped us clean up our code in regards to dependency injection.

A pain point that we had with Resolver was when we migrated our code to the the new Concurrency model when using Mainactor or other types of Actors in general.

Now that Factory seems to be a full re-write of Resolver with new features in mind, I wonder if now is a good time for you (us?) to think a bit more on how to natively support concurrency out of the box. Looking at the code, the actor model should be able to help you a lot when it comes to thread safety.

Is this something that you're open to implement/discuss for Factory?

Getting structured concurrency warning when using property wrappers

Hello,

I have recently been working on a project where I switched the Stricted concurrency checking too complete.
After doing that I end up with several concurrency warning for @Injected variables.

final class GetCurrentLyrics: GetCurrentLyricsUseCase, Sendable {
    //// Warning on this variable
    @Injected(UseCasesContainer.getCurrentMedia) private var getCurrentMedia: GetCurrentMediaUseCase

   xxxxxx rest of code
}

The @Injected variable produces the following warning: Stored property '_getCurrentMedia' of 'Sendable'-conforming class 'GetCurrentLyrics' is mutable. Could there be a way to remove this warning ?

Never the less thank you very much for this wonderful tool that is Factory.

callAsFunction build error undefined symbol

I'm using factory in a library inside a swift package. It works well. Only problem is on when using it inside a framework it cannot find the symbol call as function.

I get this error

Undefined symbols for architecture x86_64:
  "_$s7FactoryAAV14callAsFunctionxyF", referenced from:
      _$s11ChameleonUI12ThemeManagerC17pageControlConfigAC04PagefG0VvgAFyXEfU_ in ThemeManager.o
  "_$s7FactoryAAVMn", referenced from:
      _symbolic _____y_____G 7FactoryAAV 9Chameleon5ColorV in ThemeManager.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I have no clue why this happens. Do you?

Register overrides other container factories with same protocol signature

Hi Michael,

thanks for this great package! I've found an issue and maybe you can lead me to the right direction.

I have a SharedContainer similar to this:

class MyModule: SharedContainer {
    static let approve = Factory<MyProtocol<Input, Output>> { wrap(Approve()) } 
    static let complete = Factory<MyProtocol<Input, Output>> { wrap(Complete()) }
    static let reset = Factory<MyProtocol<Input, Output>> { wrap(Reset()) }
}

And my ViewModel is injecting the dependencies:

final class ViewModel: ObservableObject {
        @Injected(MyModule.approve) private var approve
        @Injected(MyModule.complete) private var complete
        @Injected(MyModule.reset) private var reset
        ...
}

My issue now is that Factory is overriding my mocks in tests with the latest definition for the same protocol signature. My assumption was that this handled per container property. (Like https://github.com/hmlongco/Resolver/blob/master/Documentation/Names.md)

extension MyModule {
    static func mockApprove(data: Output?) {
        approve.register { Fake<Input, Output>(data) }
    }

    static func mockComplete(data: Output?) {
        complete.register { Fake<Input, Output>(data) }
    }

   static func mockReset(data: Output?) {
        reset.register { Fake<Input, Output>(data) }
    }

The test:

class MyTest: XCTestCase {

    override class func setUp() {
        super.setUp()
        MyModule.mockComplete()
        MyModule.mockApprove() <-- MyModule.complete behaves after evaluation like approve
        MyModule.mockReset() <-- MyModule.approve and MyModule.complete behave after evaluation like reset
    }
    ...
}

Factory vs EnvironmentObject

Hey @hmlongco, thank you for publishing Factory and all your open source work in the Swift/iOS community!
I'm working on a SwiftUI project for which we've been using singletons for services so far. It's gaining complexity now, so I'm looking at a better option for dependency injection. Reading through the Factory readme, I'm wondering in which cases to go with a Factory-injected service and when to use a vanilla EnvironmentObject. Do you have any pointers that can help with this decision?

Closure factories compile ok but get tagged with errors by Xcode

So I have the following code where I'm using Factory to return a closure instead of a type:

public func factory() -> Container {
    Container.shared
}

public typealias DateProviding = () -> Date

public extension Container {
    var dateProvider: Factory<DateProviding> { self { { Date() } } }
}


// And later in some code...
factory().dateProvider()() 

This compiles successfully however Xcode then goes an tags it with an error even though there isn't one:

Screenshot 2023-03-30 at 17 10 30

It looks likes Xcode is miss-interpreting this code even though it compiles fine. I've tried

(factory().dateProvider)()() 
(factory().dateProvider())()
let x = factory().dateProvider()
x() 

But they all trigger the error. So far it looks like the only thing that removes it is if I do this:

let x:() -> Date = factory().dateProvider()
x() 

Any thoughts on how to get Xcode to behave?

`Singleton` scope when used with a `ParameterFactory`

I guess this isn't a bug per se but something which caught me ought as it was unexpected behaviour, so I wanted to call it out to get a view on it and whether it's perhaps an oversight / something which could potentially be added?

I recently started using ParameterFactory in the following way:

enum InputParam {
  case param1
  case param2
}

static let testDependency = ParameterFactory<InputParam, DependencyType>(scope: .singleton) {
  DependencyConcreteType(input: $0)
}

My expectation here was that the resolver would provide me back with the same instance of the DependencyConcreteType for each resolution when using param1 as the input and a different instance when resolving with the param2 input. However, this doesn't appear to be the case as the identifier (GUID) is created against the registration and this doesn't account for what params have been specified. So regardless of what the input param is set to, the resolver will return the same instance for any resolution. Is this intended behaviour? Thanks!

Add @InjectedObject property for ObservableObject compatibility

Hello, I've used Resolver for a while and just switched over to Factory. Both libraries help to circumvent common issues with EnvironmentObject, but both libraries also run into the same issue wherein you lose the ability to trigger SwiftUI views to update when a property on the object changes by default. This usually requires a bunch of boilerplate code and a required ViewModel, so there's easy way to make lightweight views the way one might with EnvironmentObject, which creates an inverse problem to the one presented by SwiftUI's EnvironmentObject.

Curious what the expectation is for working around this, or if there are plans for something like an @InjectedObject (as in Resolver) property to help account for this? I saw issue #1, but it doesn't really go into detail, and the provided snippet doesn't actually support re-rendering views (see example below), so it's not really a valid workaround for achieving the same behavior by itself.

This library seems like an extremely easy-to-use and easy-to-onboard dependency injection tool, but I would argue it's not really SwiftUI-compatible (or at least not SwiftUI-optimized) without functionality like this in place, and/or some comprehensive documentation in the README for what the expectations/workarounds are for dealing with this.

Problem

Say we want to pull AppSettings into a view, which is just a struct that has an environment property. Ideally, this would be all it takes to achieve that:

struct MyView: View {
    @Injected(Container.appSettings) var appSettings

    var body: some View {
        Text(self.appSettings.environment)
    }
}

However, when appSettings.environment is updated, the view does not reload -- which is a known limitation of this library.

If I take the snippet provided in issue #1, it doesn't resolve the problem -- the view still doesn't reload.

struct MyView: View {
    @StateObject var viewModel = MyViewModel()

    var body: some View {
        Text(self.viewModel.appSettings.environment)
    }
}

final class MyViewModel: ObservableObject {
    @Injected(Container.appSettings) var appSettings
}

Instead, I have to do something like this:

final class MyViewModel: ObservableObject {
    @Injected(Container.appSettings) var appSettings

    private var subscriptions = Set<AnyCancellable>()
    
    init() {
        // without this block, MyView will not trigger a state refresh.
        self.appSettings.objectWillChange.sink { _ in
            self.objectWillChange.send()
        }
        .store(in: &self.subscriptions)
    }
}

or this

final class MyViewModel: ObservableObject {
    @Injected(Container.appSettings) var appSettings
    @Published var environment: Environment

    private var subscriptions = Set<AnyCancellable>()
    
    init() {
        // no different than the example above unless I optimize further
        self.appSettings.$environment
            .assign(to: &self.$environment)
    }
}

Proposed Solution

A reimplementation of Resolver.InjectedObject to be included in this library:

@propertyWrapper public struct InjectedObject<T>: DynamicProperty where T: ObservableObject {
    @ObservedObject private var dependency: T
    
    public init(_ factory: Factory<T>) {
        self.dependency = factory()
    }
    
    public var wrappedValue: T {
        get { return dependency }
        mutating set { dependency = newValue }
    }
    
    public var projectedValue: ObservedObject<T>.Wrapper {
        return self.$dependency
    }
}

I don't think we need to provide an implementation for StateObject explicitly since we're not worried about a view being the owner of the StateObject -- similar to how there is no EnvironmentStateObject and EnvironmentObservedObject, for example.

That said, if we needed to (or it would help optimize or anything), we could also add InjectedStateObject for explicit conformance.

Microservice concept using Factory

Hi @hmlongco,

I've read your articles on SwiftUI architecture and they're inspiring. I notice there's a difference of Service's usage in your old articles and those in the demo project of Builder / Factory. I wonder if I understand concept of Service correctly.

From your article in 2019 SwiftUI Microservices, you define Service as:

Services, on the other hand, are created and shared among multiple views and components in our SwiftUI application by injecting them into the application environment at some level of the view hierarchy for use by elements at a lower level. They persist for as long as that level persists.

This means a view can depend on any number of services, which are small observable objects with some published properties and methods that mutate their properties.

Let's use an example SwiftUI component to demonstrate. Imagine we're building a calendar app that has a sidebar, which contains a small calendar at the top and some tabs to navigate below it, similar to Google calendar.

image

User can select a date from the calendar to display events on that date in the main screen. In the sidebar we want to get today, selected date and selected tab from services. We don't want to put them in single app state because making one single change to application state — say, changing selected date — and now every single view tree in the application needs to be walked and checked for changes. Hence I split them into 3 services.

p.s. I don't want to use TodayService and SelectedDateService inside Calendar component directly by marking them @EnvrionmentObject because Calendar may be used elsewhere which should not be affected by selected date from outside e.g. date picker for user to choose event's date when user creates an event, I don't want choosing a date in the date picker will change the selected date in the inbox view. Hence I prefer to make Calendar a "dumb" / "presentational" component.

class CurrentTabService: ObservableObject {
    enum Tab {
        case inbox
    }

    @Published var tab: Tab = .inbox
}

class TodayService: ObservableObject {
    @Published var date: Date = .init()
}

class SelectedDateService: ObservableObject {
    @Published var date: Date = .init()
}

struct SystemServices: ViewModifier {
    private static var currentTabService: CurrentTabService = .init()
    private static var selectedDateService: SelectedDateService = .init()
    private static var todayService: TodayService = .init()

    func body(content: Content) -> some View {
        content
            .environmentObject(Self.currentTabService)
            .environmentObject(Self.selectedDateService)
            .environmentObject(Self.todayService)
    }
}

struct Sidebar: View {
    @EnvironmentObject var currentTab: CurrentTabService
    @EnvironmentObject var today: TodayService
    @EnvironmentObject var selectedDate: SelectedDateService

    var body: some View {
        VStack {
            Calendar(today: $today.date, selectedDate: $selectedDate.date)
            SidebarItem("Inbox", currentTab: $currentTab.tab)
            ...
            }
        }
    }
}

struct AppView: View {
    var body: some View {
        HStack {
            Sidebar()
            MainScreen()
        }
        .systemServices()
    }
}

Then from your later article in March SwiftUI: Choosing an Application Architecture, you say that:

With a View Model, we want to move as much of the logic out of the view as possible, leaving behind code that’s dead simple to understand.
That’s a good example of separation of concerns. We put our business logic on one side of the fence, and all of our view presentation and layout on the other.

Using our previous example, it means we should have a SidebarViewModel to "put our business logic on one side of the fence, and all of our view presentation and layout on the other." We will need to inject services into SidebarViewModel that control current tab, selected date and today. It then becomes the mediator between Sidebar view and those services e.g. get the values from them, expose methods to modify those values, perhaps using Factory.

struct Sidebar: View {
    @StateObject var viewModel: SidebarViewModel = .init()

    var body: some View {
        VStack {
            Calendar(today: $vm.today, selectedDate: $vm.selectedDate)
            SidebarItem("Inbox", currentTab: $vm.currentTab)
               ...
            }
        }
    }
}

Which way would you choose if you were me given that we can use Factory or Resolver for DI nowadays? Another question is how should I design the services using Factory, since I want to store values e.g. today, selected date and current tab in those services, and then make them publishable inside the SidebarViewModel? Should I put them altogether in 1 service say AppState or keep them split in 3 services when I use Factory?

Thanks,
Joseph

Circular dependency wrongly detect

Hi,

With the resent version we have a circular dependency detected but I think it's wrong. It appears after the version 1.2.9.

We have a container that exposes a ParameterFactory dependency. It provides different instances for different team. Each team has its own Container which provide an instance from the ParameterFactory dependency.
Depending on how we use Factory generate the instances, a circular dependency error is thrown.

Better than word to explain, here is a test to illustrate the issue

final class TeamLogger {
    let teamName: String

    init(teamName: String) {
        self.teamName = teamName
    }

    func log(_ message: String) {
        print("\(teamName) - \(message)")
    }
}

final class LoggerProvider {
    func logger(for team: String) -> TeamLogger {
        return TeamLogger(teamName: team)
    }
}

final class LoggerProviderContainer: SharedContainer {
    private static let loggerProvider = Factory(scope: .cached) {
        return LoggerProvider()
    }

    static let logger = ParameterFactory<String, TeamLogger> { teamName in
        return loggerProvider().logger(for: teamName)
    }
}

final class TeamAContainer: SharedContainer {
    static let teamALogger = Factory(scope: .cached) {
        LoggerProviderContainer.logger("TeamA")
    }
}


final class FactoryCircularDependencyTests: XCTestCase {

    override func setUp() {
        super.setUp()
        Container.Registrations.reset()
        Container.Scope.reset()
    }

    // ERROR 
    func testCircularDependencyError() {
        let logger = TeamAContainer.teamALogger()

        logger.log("Hello")
    }

    // OK
    func testNoCircularDependencyError() {
        let logger = LoggerProviderContainer.logger("TeamA")

        logger.log("Hello")
    }
}

testCircularDependencyError throws Fatal error: circular dependency chain - FactoryTests.TeamLogger > FactoryTests.TeamLogger .

ParameterService Question

Hi there! This is a phenomenal library. I've integrated it extensively for a complex cross-platform commmunications app. A few questions:

  • Is there a way to dynamically create Scopes at runtime? Or is compile-time definition a fixed constraint?
  • For the ParameterService -- are the objects that are created by the factory callback cached at the DI layer? Or is it just the factory that is cached? For example -- if I wanted to use a ParameterService registration for a factory that creates arbitrary view models, initialized w/provided parameters -- are those objects cached? For the N+1 occurence that a given ParameterService receives the same parameters, is the previously-produced object (returned in the factory callback) returned?

Issue with optional service

FactoryExample.zip

I have included an example where an incorrect result is being returned. In this example the idea is that my FactoryService makes a userService available in the Container. The initial value is nil. Another target implements an AuthenticationService which sets the userService, as appropriate.

One of the two tests fails - the one that passes tests that the userService is nil. The second test then registers a user, via the AuthenticationService, but this result is still nil.

Edit:
I have left the original example as is, as this issue occurs even if the service is in the same target. The issue appears to be caused by using an optional value.

[Question] How to use with a VIPER architecture?

I love the simplicity of this DI package, but I'm finding the documentation a little confusing. My adoption of the package would depend on how it deals with a 'Clean Architecture' used in a professional workspace. Right now I'm struggling to understand how to use this package with a VIPER architecture. We use a similar structure to here:
https://github.com/theswiftdev/tutorials/blob/master/VIPER/VIPERAndSwiftUI/VIPERAndSwiftUI/Sources/VIPER.swift

I began with this (below) but it doesn't compile (not even sure this is the correct approach):

import Foundation
import SwiftUI
import Factory

// MARK: - Router
typealias ListViewRouterInterface = any RouterInterface & ListViewRouterPresenterInterface

protocol ListViewRouterPresenterInterface: RouterPresenterInterface {
    func showDetails(for animal: Animal) -> any View
}

// MARK: - Presenter

typealias ListViewPresenterInterface = any PresenterInterface & ListViewPresenterRouterInterface & ListViewPresenterInteractorInterface & ListViewPresenterViewInterface

protocol ListViewPresenterRouterInterface: PresenterRouterInterface {

}

protocol ListViewPresenterInteractorInterface: PresenterInteractorInterface {
    func didLoad(animals: [Animal])
}

protocol ListViewPresenterViewInterface: PresenterViewInterface {
    var viewModel: ListViewModel? { get set }
    func onAppear()
    func onBtnPress(animal: String)
}

// MARK: - Interactor
typealias ListViewInteractorInterface = any InteractorInterface & ListViewInteractorPresenterInterface

protocol ListViewInteractorPresenterInterface: InteractorPresenterInterface {
    func fetchItems()
}

extension Container {
    static let apiService = Factory<APIServiceProtocol>(scope: .shared) { APIService() }
}

class ListViewContainer: SharedContainer {
    static let viewModel = Factory<ListViewModel>(scope: .shared) { ListViewModel() }
    static let presenter = Factory<ListViewPresenterInterface>(scope: .shared) { ListViewPresenter() }
    static let interactor = Factory<ListViewInteractorInterface>(scope: .shared) { ListViewInteractor() }
    static let router = Factory<ListViewRouterInterface>(scope: .shared) { ListViewRouter() }
}

final class ListViewModule {
    @Injected(ListViewContainer.viewModel) private var viewModel
    @Injected(ListViewContainer.presenter) private var presenter
    @Injected(ListViewContainer.interactor) private var interactor
    @Injected(ListViewContainer.router) private var router

    func build() -> some View {
        presenter.viewModel = self.viewModel
        let view = ListView(presenter: presenter)
        presenter.interactor = self.interactor
        presenter.router = self.router
        interactor.presenter = self.presenter
        router.presenter = self.presenter
        return view
    }

Do you have any advice on how to do this in a VIPER architecture? I think this would be a great example to add to your samples folder. The fact that VIPER has various Input and Output contracts make it difficult.

Initialize services with @MainActor property wrapper

Hi, I have the following issues regarding initalizing a service which should execute its code on main thread.

So I have a service call LoginService:

@MainActor internal final class LoginService: ObservableObject { @MainActor internal func login(to route: MainRoute) {} }

But when I try to inialize this service i got the following compiler error:

static let loginService = Factory { LoginService() as LoginServiceProtocol }

--> Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context`

How should I handle this? Should I only add "MainActor" property wrapper to the functions instead of the whole object?

Thanks in advance.

TestUnit: I can't register

Hello,

I read the other ticket about the register issue but it didn't help me and mine is a little bit different.

The register method doesn't work ONLY during the TestUnit

Here my situation:

---- Container ----

class CustomContainer: SharedContainer {
        static let poc = Factory<String>(scope: .singleton) {
            "Initial project"
        }
}

---- ViewModel ----

final class ViewModelPoc {
    @LazyInjected(CustomContainer.poc) private var poc

    func unitTestMethod() {
        print("Result: \(poc)")
    }
}

---- Test Unit ----

class SimpleTests: XCTestCase {

    override func setUp() {
        super.setUp()
        CustomContainer.poc.register { "Test project" }
    }

    func testMethod() {
        ViewModelPoc().unitTestMethod()
    }
}

And when I run the test the consol display "Result: Initial project"

If you have any suggestions ?
Thanks

Injected does not use a newly registered dependency

I was expecting @Injected to use a dependency that I registered in my unit test, but turns out it depends on when the mocking code is called. I believe it is similar to this #28.

The implementation of Injected is not what was expected. It stores the dependency on initialization, which means if we register a factory later, it won't use the new factory. Shouldn't it store the factory instead?

I make the desired behaviour in my fork ca2b0dc

Factory 2.0! Input on Factory's future is needed!

Factory is evolving and I'm currently working on Factory 2.0 which adds true container-based dependency injection! This allows Factory to provide a variety of traditional dependency injection and service locator strategies.

class ContentViewModel: ObservableObject {

    // Old-style Factory 1.0 static service Locator
    let oldSchool = Container.oldSchool()

    // New Factory 2.0 shared service Locator
    let service = Container.shared.constructedService()

    // Constructor initialized from container
    let service2: MyConstructedService

    // Lazy initialized dependencies from passed container
    private let container: Container
    private lazy var service3: MyConstructedService = container.constructedService()
    private lazy var service4: MyServiceType = container.cachedService()

    // Annotated, keyPath-based dependency injection from default shared container
    @Injected(\.constructedService) var constructed

    // Annotated, keyPath-based dependency injection from a custom container
    @Injected(\MyContainer.anotherService) var anotherService

    // Constructor with passed container
    init(container: Container) {
        // construct from container
        service2 = container.constructedService()
        // save container reference for lazy resolution
        self.container = container
    }

}

Supporting containers has been one of my goals for awhile now, as it dramatically increases the environments and applications in which Factory can be used and considered.

But, as with most things, there's a catch: In order to do this the dependency definition has to change, making this a breaking change between 1.0 and 2.0.

Here's the existing mechanism.

extension Container {
    static let myServiceType = Factory<MyServiceType> { 
        MyService() 
    }
}

And here's a version of the same thing in Factory 2.0.

extension Container {
    var service: Factory<MyServiceType> {
        Factory(self) { MyService() }
    }
}

The Factory is now defined as a Container Member, and not a Container Class Member as is done today.

Note that three things must occur to make container Factory definitions work as expected.

  1. The Factory definition is now returned as a computed value.
  2. The Factory return type must be explicitly specified (e.g. Factory<MyServiceType>).
  3. The Factory requires a reference to its container. (self)

This adds a bit of extra code, but makes Factory much, much more powerful.

Note the basic definition could be written in several ways:

extension Container {
    var service1: Factory<MyServiceType> {
        Factory(self) { MyService() }
    }
    var service2: Factory<MyServiceType> {
        .init(self) { MyService() }
    }
    var service3: Factory<MyServiceType> {
        factory { MyService() }
    }
    var service4A: Factory<MyServiceType> {
        factory(scope: .shared) { MyService() }
    }
    var service4B: Factory<MyServiceType> {
        shared { MyService() }
    }
}

The first is fully explicit. The second uses the .init shorthand. The third uses a helper function on the container that returns the correctly bound Factory; and the fourth version demonstrates the same with the scope syntax added. The fifth variant adds a few more helpers that do the same thing as factory but specifically indicates the scope (unique, singleton, shared, etc.) at the same time.

At this point in time I'm considering going with the later option exclusively, as it ensures the correct binding and also requires the developer to explicitly consider and define the desired scope for a given factory.

extension Container {
    service6: Factory<MyServiceType> {
        unique { MyService() }
    }
    var service7: Factory<MyServiceType> {
        shared { MyService() }
    }
}

ParameterFactory would be going away as well, as it's easy to simply do...

extension Container {
    func parameterized(_ n: Int) -> Factory<ParameterService> {
        unique { ParameterService(count: n) }
    }
}

But updating and reseting services would work much as it does today.

    Container.shared.service.register { MockServiceN(8) }

Or it can be done as follows if you have access to the specific container. This version changes the behavior on that instance of that container and nowhere else.

    container.service.register { MockServiceN(8) }

This leaves me a few questions.

It's possible to make Factory 1.0 and 2.0 work together, but I'm inclined to deprecate the existing methodology as the two approaches differ somewhat in behavior, in how dependencies are managed, and, of course, supporting both the old and new code styles increases the library size.

So...

  1. Should Factory 1.0 be deprecated?
  2. Or should we accept that Factory 2.0 will be a breaking change and be done with it?
  3. And in any case, which definition style (1-4) shown above would be preferred? (Or just provide all of 'em?)

One drawback to the service4 style is that containers start to get "busy" with predefined helper functions (unique, shared, singleton, cached) in addition to the factory definitions.

I really want Factory to be the best DI system for Swift, and to do that I really need some help here. So leave a comment if you approve, disapprove, or have questions.

Canvas Preview Mock Override Requires Play Button

Thanks for your excellent work here Michael! I'm a fan of Resolver and an even bigger fan of Factory.

When looking at the FactoryDemo project ContentView preview, I don't see the MockService2 override actually taking effect until I click the canvas play button. Is there a way to work around this, or is this the expected behavior?

image

image

It would be awesome to have multiple previews with different mocked data similar to the code below and see the differences without having to click the play button on each. Is this possible with Factory?

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            let _ = Container.myServiceType.register { MyService() }
            ContentView()
            
            let _ = Container.myServiceType.register { MockService2() }
            ContentView()
        }
    }
}

This question was inspired by your article where you demonstrated previewing the different states of the AccountListView with a different loader:

struct AccountListView_Previews: PreviewProvider {
  static var previews: some View {
    Group {
      let vm2 = AccountListViewModel(loader: MockTwoAccounts())
      AccountListView(viewModel: vm2)
            
      let vm0 = AccountListViewModel(loader: MockNoAccounts())
      AccountListView(viewModel: vm0)
            
      let vme = AccountListViewModel(loader: MockAccountsError())
      AccountListView(viewModel: vme)
    }
  }
}

How can I deal with errors thrown during resolving?

I'm guessing this has come up before :-) But what sort of approaches are there for dealing with errors that are thrown during resolving?

For example, if I have this (which won't compile at the moment):

public extension Container {
    var service: Factory<MyProtocol> { self { try MyService() }.singleton }

And I want to somehow capture the error from the service init so I can display a message to say something went wrong, is there a way to neatly handle it?

one thought is to make the service optional and use a try?. But in my case the registration is for a singleton and the error is possible but highly unlikely so I'd kinda like to keep the registration non-optional and somehow redirect the error.

any thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.