Replies: 5 comments 3 replies
-
This is probably a good topic for a video/blog post! Think after the basic tutorials, others wonder this as well. |
Beta Was this translation helpful? Give feedback.
-
maybe send me a sample of the code you would break up and can give you some strategies from there |
Beta Was this translation helpful? Give feedback.
-
Thank you kindly for the follow up. I was looking at this piece of code here: https://github.com/aykaramba/edgar/blob/main/edgar.lisp And I was looking at splitting that up into separate files in an intelligent way. I am looking for ideas, strategies and for any directions for topics that I should be googling so that I can explore, iterate and learn how to start thinking about code organization. In the linked example, 90% of the code is ui code nested in (let* ...) forms and that poses some challenges about how to split up such code into separate files, at least based on my current noob understanding. Thank you kindly for any advice! |
Beta Was this translation helpful? Give feedback.
-
I always organically grow my applications. So I start as you have with one file. I only begin to split things to multiple files as you are noticing starts to need physical organization. For Lisp files do not mean anything and the tools used for Lisp CLOG Builder, Emacs or Lem all have tools to navigate code quickly and they physical location matters little.
In fact I would suggest as an exercise change that into a macro that returns a function such that you could write: (set-on-click btn-y (btn-letter-handler "y")) as a hit hint - (change-ui-state-letter btn-y) should be (change-ui-state-letter obj) and same for css-class-name btn-y) should be css-class-name obj) :) the OO approach would be to make a new type of button that knows it is a Y button and on creation sets its own handler |
Beta Was this translation helpful? Give feedback.
-
(defpackage #:calcdemo
(:use #:cl #:clog #:clog-web)
(:export start-app))
(in-package :calcdemo)
;; By using an app data object that is unique for each instance you can also
;; divide up your code - although keep in mind this creates a coupling between
;; functions that is akin to using globals
(defclass app-data ()
((display :accessor display)
(key-grid :accessor key-grid)))
(defparameter *grid* '((1 2 3) ; this is a "litteral" form of a list and any change to the
(3 5 6) ; list is "unspecified" and potentially can cause a crash
(7 8 9))) ; to your lisp)
(defun send-number (obj num)
(let ((app (connection-data-item obj "app-data")))
(setf (text-value (display app)) num)
(mapcar (lambda (row)
(mapcar (lambda (col)
(setf (background-color col) (rgb (random 256) (random 256) (random 256))))
row))
(key-grid app))))
(defun on-new-window (body)
(let ((app (make-instance 'app-data)))
(setf (connection-data-item body "app-data") app)
(setf (title (html-document body)) "Calc Demo")
(setf (display app) (create-form-element body :text))
(create-br body)
(let ((rows (list)))
(mapcar (lambda (row)
(let ((cols (list)))
(mapcar (lambda (col)
(let ((btn (create-button body :content (format nil "~A" col))))
(set-on-click btn (lambda (obj)
(send-number obj col)))
(push btn cols)))
row)
(push cols rows)
(create-br body)))
*grid*)
(setf (key-grid app) rows))))
(defun start-app ()
(initialize 'on-new-window
:static-root (merge-pathnames "./www/"
(asdf:system-source-directory :calcdemo)))
(open-browser)) |
Beta Was this translation helpful? Give feedback.
-
I am now starting to write over 1000 lines of code in my test applications and I am getting comfortable with the general concepts in Common Lisp and CLOG. I have a question about splitting up applications into separate files in a specific scenario.
In a typical webdev scenario, I could easily split up an application into separate packages and reload the entire app on a new route and load up the new package to get a new self contained instance of that package and go from there.
In my current scenario, I am only working in one package and developing a single page application with no routes. In a typical scenario, the on-new-window function will initialize (clog-gui-initialize body) and then run a let* form which ends up being a root "container" of most of my application code that deals with the user interface. Any code that does not deal with the user interface will typically be located at the "root" of the code structure and be called with functions and return what it needs to return, of course.
In effect, what ends up happening is that all of my ui code ends up being encapsulated in the lexical scope of the (let* ...) form and pulling out ui code into a separate file that still needs to access ui components contained within lexical scope does not seem to work.
What strategies should I think about and google in order to refactor my code into a more modular structure?
Beta Was this translation helpful? Give feedback.
All reactions