waffle
waffle copied to clipboard
Clean up code
- [ ] Safety
- [x] Put each mode's event handler in their own module
- [ ] Clean comments, including moving TODOs and FIXMEs to issues and their details
- [ ] Document
- [ ] Modularize better so more stuff is moved out of UI
- [ ] Modularize better; put thing in their own modules appropriately and submodules etc
- [ ] Better imports
- [x] Better exporting+module documentation (specifically import certain things!)
A lot of stuff could make better use of higher order functions. Something which comes to mind are stuff like progress module and the stuff like searchGet and gopherGet, etc.
The history items in progress.hs should go in their own module. They're currently in there because of a circular import problem.
Some of @Garmelon's suggestions:
-
[x] Explicit exports.
module Bla (foo, bar) where. This way:- you can control what is exported and in which order (useful for documentation)
- you can easily add haddock headings in order to organize your documentation better
- the compiler can warn you of unused code/functions (functions that are never used and never exported)
-
[x] Switch to using
Data.Textinstead ofStringIf only to learn about how it works.Data.Textusually has better performance thanString's linked-list-of-characters approach. It also has a few common string manipulation functions thatStringis kinda missing. Some people argue forTextto replaceStringentirely. -
[x] Rename
GopherClienttoGopherUse the module only to model the gopher protocol side of things. Leave out functions that don't use that protocol representation (such asgopherGet; NOTE: I'm guessing I should have aNetwork.hs). As a rule of thumb: No IO required. Also make sure there are no partial functions (different than partially applied) and you don't use error or undefined anywhere (don't use them in other modules either, if at all possible). Programming is pretty much all about manipulating data. Having a good representation for the data helps a lot. I'd say this becomes even more obvious in Haskell, since here you have better ways to represent your data out-of-the-box than in languages like Java or Python. When in doubt, roll your own types instead of usingEither(Eitheralready treats its left and right arguments differently due to its various instances.Leftis usually used to hold some sort of error, whileRightis used to hold a successful result). -
[ ] Separate the UI into different widgets that only need to know their own state. This is where I'd need to know more about the UI and its different interactions: Try to separate the UI into different widgets that only need to know their own state. They should not need to know any sort of global state (GBS) nor rely on a common resource name type. You can use the way brick widgets are structured and structure your own widgets after those.
-
[ ] Design an application state and application using the widgets from the previous step. This application module should use the widgets, not the other way around. Try to keep features general and loosely coupled. Extract things into modules wherever it makes sense. A single client feature (like the history) does not necessarily need to be confined to a single module. For example, I could imagine one module that lets you store a history of states of any type, and a history widget that can display some of the data types from the history module.
Maybe even start UI/Modes/*.hs?
you're supposed to keep widgets in app state and manipulate things from there! that's much more efficient than rebuilding every dang time