Comments (17)
Concerning YAML config reader: I figured it is not really needed at this point, as the environment is configured via Docker env variables. Might be needed if installed without Docker (that's how we started). So I just left it like it is.
from photoprism.
Config should use functions, not fields, to return values. It's on my personal to do list. Again, there should be good test coverage first.
from photoprism.
What do you mean functions instead of fields? I mean, Go is simple. It doesn't very much like getters. :) It's not Java.
Things like these are not idiomatic:
type MyStruct struct{
Field1 string
}
func (m MyStruct) GetField1() string {
return m.Field1
}
These are not things you want in Go. :)
from photoprism.
Also, even if it's environment properties, that config part where you load in the file and then have a bunch of ifs defining the variables if they exists, it's just like using a marshaller in the end. They'll be nil if nothing is defined in the file.
Hmm, that reminds me. I should set omitempty
. :)
from photoprism.
For example, I started doing this so that not every single sub-directory needs to be defined in the config file (c.AssetsPath should be changed to c.assetsPath when refactoring is done):
func (c *Config) GetAssetsPath() string {
return c.AssetsPath
}
func (c *Config) GetTensorFlowModelPath() string {
return c.GetAssetsPath() + "/tensorflow"
}
So now of course you could argue that all those paths could be properly populated upfront and the functions are not needed.
from photoprism.
You suggest directly populating config via yaml.Unmarshal()
? Is that a good idea, assuming you might want at least a little bit of abstraction and validation between the file and what you use internally? I see you can do it like that, I just want to think about it before we go that way (if that's what you suggest).
from photoprism.
So, Go isn't like that. Go is a very simplistic, C style language, with limited OOP capabilities. It love what's simple. Marshalling works in huge projects and in Go itself and it various other situations without making a getter setter. Getter setters are a reminiscence of Java, PHP and other languages who promote OOP. Go is more like C in this regard. As simple as possible don't think about it too much. :)
In the above example you provide GetAssetsPath would be a good thing only if it's doing something before accessing the property. Like, validation, or default setting, or something else. In this form is absolutely useless and clutters the code needlessly.
Let me ask you this. What would the abstraction be good for? What would it actually add in this situation? What do you expect to get out of a layer of indirection like that?
If you want an abstraction just to have an abstraction you don't need the abstraction. :)
from photoprism.
For me, Go is Oberon that looks like C. Using functions is not OOP.
The reason why I started to refactor this is that some config values had in fact be returned by functions like GetTensorFlowModelPath()
, unless I want to put every single sub-directory in the config file (which also means the config file would change a lot and become big, fat and ugly).
As a developer, I want to get all config values the same way and I don't want to investigate if a particular value needs abstraction or not. That's simplicity.
from photoprism.
So, you have one case where having a function is okay, because you are also setting something while getting the data. But then that's not a getter any more that's a function providing some information and a possible side effect as an extra. :)
The rest, is still simply returning a field. Which doesn't require a function at all and imho only convolutes the code. Reminds me of long forgotten days of Java Beans shudders in horror.
Thus, by that logic, if your config happens to have 20 fields, you'd write 20 functions for each field? :)
from photoprism.
Before we use this ticket to start a discussion about Java Beans, here are two examples from the actual code:
func (c *Config) GetPublicBuildPath() string {
return c.GetPublicPath() + "/build"
}
func (c *Config) GetDb() *gorm.DB {
if c.db == nil {
c.ConnectToDatabase()
}
return c.db
}
from photoprism.
Example for what? GetPublicPath
there does not need to be a function. That's the only thing I'm talking about here. The rest is fine not counting the fact that they don't have to be exported. If I remember correctly neither of them are used outside this package. Or maybe dB does. But that's not the point here.
All im saying is that unless you modify the data there is no need for the function. If you modify the data it's no longer a getter but a method that provides extra information.
from photoprism.
All im saying is that unless you modify the data there is no need for the function. If you modify the data it's no longer a getter but a method that provides extra information.
Exactly the kind of detail I don't want to care about when I use the data (in this case paths) somewhere else in the code. This might change and then you need to do a lot of refactoring just to save a function here and now.
Simplicity also lies within a uniform interface and abstraction of implementation details. The same logic was used against Pascal by the C crowd who preferred to not have strings in return for a little bit of performance. Every C developer now has to care about the implementation details of strings and there are a lot of security issues related to it and the manual memory management. That's not simplicity.
If this makes it more logical: The config paths might be dynamic later, if we build a multi-user version. I don't want the code to assume they are constant.
from photoprism.
Okay then. 😊👌
from photoprism.
Good that we talked about it. This is the kind of information that is valuable as inline comment or in the developer guide.
from photoprism.
@Skarlso Closing this as there have not been more contributions. Thank you for the pull requests and the great advice! 👍
I've created a page in our Wiki related to this: Code Quality
from photoprism.
@lastzero So sorry man. I got completely swamped. :/ Once I can pick up the threads of my life again, I'll reopen and work on this some more. :) Happy to have helped out though! :)
from photoprism.
@Skarlso Happy new year and thank you for the feedback ⭐️ You're welcome back anytime!
from photoprism.
Related Issues (20)
- Idea: CalDAV support / Memories Improvement
- BUG: Incorrect Creation/Modification Date for Uploaded Files HOT 1
- Search: Allow sorting of results by UTC instead of local time HOT 2
- Setup: Improve docker-compose.yml inline docs for INIT and MARIADB_PASSWORD HOT 6
- Frontend: Upgrade MapLibre GL JS from v3.6 to v4.0
- MariaDB: Show info when waiting for the database to become available HOT 11
- Albums: Fix links to albums in the settings tab of the edit dialog HOT 11
- Indexed Image Names Differ From Original File Names
- Index: Create a new photo or find an existing one if the photo UID has been restored from a sidecar YAML file HOT 1
- Library: Live photo / video preview loading delay (1-2 seconds)
- Video: Allow streaming of all HEVC videos under Windows, e.g. by transcoding to AVC HOT 4
- WebDAV: Adding TrueNAS as a service for syncing files does not work HOT 2
- Idea: As a User, I would like to see the current upload speed of the file being uploaded in the iOS/Android app
- Support for Cryptomator FS under Windows HOT 1
- Setup: Provide ARMv7 installation packages HOT 1
- Develop: Upgrade base image to Ubuntu 24.04 LTS (Noble Numbat)
- task "convert" takes a very long time to sort through the already encoded files HOT 1
- Picture Handling: Use Archive to conveniently manage second priority pictures
- Docker Photoprism error after server reboot
- Stacks: Stack files by dc:identifier HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from photoprism.