# Refactoring Julia Modules for Shape Representation and Canvas Drawing

**URL:** <https://discourse.julialang.org/t/refactoring-julia-modules-for-shape-representation-and-canvas-drawing/114095>\
**Category:** Performance\
**Tags:** module, multidispatch\
**Created:** [May 10, 2024, 10:38am UTC](https://discourse.julialang.org/t/refactoring-julia-modules-for-shape-representation-and-canvas-drawing/114095 "2024-05-10T10:38:11Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Akhil\_Akkapelli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/akhil_akkapelli/32/202792_2.png) [@Akhil\_Akkapelli](https://discourse.julialang.org/u/Akhil_Akkapelli)\
**Post date:** [May 10, 2024, 10:38am UTC](https://discourse.julialang.org/t/refactoring-julia-modules-for-shape-representation-and-canvas-drawing/114095/1 "2024-05-10T10:38:11Z")

</div>

I have two Julia modules, “Shape.jl” and “Canvas.jl”, which define shapes and a canvas for drawing them. The code works as intended, but I’m wondering if there’s a cleaner and more efficient way to structure these modules.

# Shape.jl module:

```julia-auto
module ShapeMod
export Shape, Rectangle, Circle, Refine!

abstract type Shape end

mutable struct Rectangle <: Shape
  Colour::String
  Width::Real
  Height::Real
  Rectangle(;Colour::String="black", Width::Real=.5, Height::Real=.5) = new(Colour, Width, Height)
end

function Refine!(Rect::Rectangle;Colour::String=Rect.Colour, Width::Real=Rect.Width, 
  Height::Real=Rect.Height)
  Rect = Rectangle(Colour, Width, Height)
end

mutable struct Circle <: Shape
  Colour::String
  Radius::Real
  Circle(;Colour::String="black", Radius::Real=.5) = new(Colour, Radius)
end

function Refine!(Cir::Circle;Colour::String=Cir.Colour, Radius::Real=Cir.Radius)
  Cir = Circle(Colour, Radius)
end

end #module

```

# Canvas.jl module:

```julia-auto
module CanvasMod

include("ShapeMod.jl")
import .ShapeMod: Shape, Rectangle, Circle, Refine!

export Canvas, Refine!, RefineCanvas!

mutable struct Canvas
  CanvasShape :: Shape
  XPosition :: Real
  YPosition :: Real
  Canvas(;CanvasShape::Shape=Rectangle(), XPosition::Real=0, YPosition::Real=0) = new(CanvasShape, XPosition, YPosition)
end

function Refine!(Canv::Canvas; CanvasShape::Shape=Canv.CanvasShape, XPosition::Real=Canv.XPosition, YPosition::Real=Canv.YPosition)
  Canv = Canvas(CanvasShape, XPosition, YPosition)
end

function RefineCanvas!(Canv::Canvas; CanvasShape::String=typeof(Canv.CanvasShape), Colour::String=Canv.CanvasShape.Colour, Width::Real=Canv.CanvasShape.Width, Height::Real=Canv.CanvasShape.Height, Radius::Real=Canv.CanvasShape.Radius, XPosition::Real=Canv.XPosition, YPosition::Real=Canv.YPosition)

  CanvShape = getfield(Canv, :CanvasShape)
  if(CanvasShape == Rectangle)
    Refine!(CanvShape, Colour, Width, Height)
  elseif(CanvasShape == Circle)
    Refine!(CanvShape, Colour, Radius)
  end

  Canv = Refine!(Canv, CanvShape, XPosition, YPosition)

end

end #module

```

Is there a more concise and idiomatic way to define these modules, especially regarding the constructors and the `Refine!` functions? Any suggestions for improving the structure and readability of the code would be appreciated.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 10, 2024, 11:21am UTC](https://discourse.julialang.org/t/refactoring-julia-modules-for-shape-representation-and-canvas-drawing/114095/2 "2024-05-10T11:21:53Z")

</div>

One thing:

```julia
mutable struct Canvas
  CanvasShape :: Shape

```

`Shape` is abstract type, so this struct is type-unstable. Use, better:

```julia
mutable struct Canvas{S<:Shape}
  CanvasShape :: S

```

So to make it parametric for the shape type.

Then, you can use dispatch easier to define your `RefineCanvas!` function

```julia
function RefineCanvas!(Canv::Canvas{Rectangle}; etc...) 
    Refine!(Canv.CanvShape, Colour, Width, Height)
    Canv = Refine!(Canv, CanvShape, XPosition, YPosition)
    return Canv
end

function RefineCanvas!(Canv::Canvas{Circle}; etc...) 
    Refine!(Canv.CanvShape, Colour, Radius)
    Canv = Refine!(Canv, CanvShape, XPosition, YPosition)
    return Canv
end

```

as a styling note, usually variables are written in lowercase, and uppercase is used to identify types.
