Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split code into modules #29

Open
femtotrader opened this issue Jan 19, 2025 · 4 comments
Open

Split code into modules #29

femtotrader opened this issue Jan 19, 2025 · 4 comments

Comments

@femtotrader
Copy link

Hello,

currently your code have only one module I think it's a better Julia practice to split code into modules.
If I were you I will at least create an Exchanges module.
I don't know if I will break each separate exchange into module.
I will probably do that because I will create 2 kind of objects per exchange:
1 for dealing with REST API
1 for dealing with Websocket
and have a module surrounding them.

Any opinion?

@g-gundam
Copy link
Owner

Maybe

Although I have a tiny bit of websocket code here, I haven't thought too hard about how I wanted to use it. The RESTful code in this library supports archival of 1 minute candles by calling save!. With websockets, I had thought maybe I could support some kind of continuous archival, but I never implemented this.

Regarding the existing websocket code like struct CryptoMarketData.Session and subscribe(uri), you don't have to take that code too seriously. Maybe I shouldn't have even put that code in CryptoMarketData.jl in the first place, but I was playing around with websockets to get a feel for it. Also, nothing really depends on that code, so it can be blasted away if necessary.

I think spawning a task to contain the websocket connection was a good idea, but the implementation needs to be tightened up, and I want to rename subscribe to connect.

Back to Modules

Note

I'm open to introducing more modules.

In an ideal world, how would you reorganize this code? Let's take Bitstamp as the test case.

  • Under what modules would the RESTful code for Bitstamp live?
  • Under what modules would the websocket code for Bitstamp live?

@femtotrader
Copy link
Author

I'd put both RESTful code and Websockets in the same module named Bitstamp in in a module named Exchanges

g-gundam added a commit that referenced this issue Jan 22, 2025
This is an experiment to see if #29 is worth doing.
@g-gundam
Copy link
Owner

I made a branch called modules, and I gave it a try on just Bitstamp, but it got really awkward. The biggest problem was that these exchange-specific methods need to be in CryptoMarketData.

# functions with exchange-specific methods
export csv_headers
export csv_select
export ts2datetime_fn
export candle_datetime
export short_name
export candles_max
export get_markets
export get_candles

The machinery around save!() and load() were written with that assumption in mind.

@femtotrader
Copy link
Author

You can keep these functions in the Bitstamp module.
Don't export them. But decide to import them (with using) where you need them (ie in the CryptoMarketData module)

Here is a summary of how modules are working. (LLM paragraph)

Modules in Julia

Modules in Julia are separate namespaces that help organize code and control variable/function scope. Here's how the main module-related commands work:

Creating a Module

module MyModule
    # Module contents go here
end

Export

The export command specifies which names from a module should be made available when another file uses using:

module MyModule
    export my_function, MyType  # These will be available when using MyModule
    
    function my_function()
        println("Hello!")
    end
    
    struct MyType
        x::Int
    end
    
    function internal_function()  # Not exported, only accessible with MyModule.internal_function
        println("Internal!")
    end
end

Importing Commands

  1. using - Most common way to import modules:
using MyModule  # Imports all exported names
using MyModule: my_function  # Imports specific exported names
  1. import - More explicit control:
import MyModule  # Imports the module, must use MyModule.function_name
import MyModule: my_function  # Imports specific name, can use directly
  1. using .MyModule - Relative import from current module
using .MyModule  # Import from submodule
using ..MyModule  # Import from parent module

Key Differences

  • using MyModule:

    • Imports all exported names into current namespace
    • Can use functions directly: my_function()
    • Cannot extend imported functions without explicit import
  • import MyModule:

    • Must use qualified names: MyModule.my_function()
    • Can extend functions with new methods
    • More explicit and prevents naming conflicts

Include Files

You can split module code across multiple files using include:

module MyModule
    include("helpers.jl")
    include("types.jl")
    
    # Rest of module code
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants