|
Your primary consideration is: how many users does it need to support; and how many users are "logging in and out at any given time".
Then one can say what is feasible and how it will likely perform.
There are usually 3 things to consider; you only get to pick 2: cheap, fast and good.
(And for about $5 per month you could interface with a Sharepoint Online "list" ... which is transparently backed by you know what).
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
modified 18-Jan-24 13:12pm.
|
|
|
|
|
How many users? Well, considering a web based email service, the answer is "many". You will not be getting a definite number there, that will depend on the succes of the implentation, it's performance and the final pricing for the endlooser. Aw, and a little bit of marketing - it "only" has to be better or more secure than the free Proton-mail alternative.
There's no "pick 2 of these 3"; it won't be cheap nor fast, nor good, if you create your own datastorage alternative in favor of using a free product that is built solely to store and retrieve data and which has been optimized for years to do exactly that one task. In this case it is "pick 0 of these 3", literally.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Your assumption of "many" has no basis in fact; as do all your others. It could be a "home project". As others have pointed, OP appears to be "exploring". I was once going to build the ultimate boolean database engine.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
As a home project, you'd expect "many" users (not quantifiable). He or she might be exploring, but that doesn't show in the question, does it? It asks specifically about "a web based email service". Do enlighten me, what kind of number of users would you assign to that question, besides my vague answer of "many"? Do explain?
I give no sh*t about your bool DB engine. This is the Design and Architecture Cat, and the headline speak volumes that you missed. My assumption is based on the subject line and one does not build a webbased email for five users. I'm sorry I had to explain that. How much "many" is, is not relevant to you either. It is not like Google is that different from ProtonMail. 10k users or 100M users is the same project, with more servers. It does not require a special command line compiler directive if that changes, it just requires good design. Which start by NOT WRITING A DAL. Not by inquiring to quantify what "much" is.
I never assume. Now, get off my lawn.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Remember Morrissey's lyrics in The Smiths:
"It's so easy to laugh. It's so easy to hate. It takes guts to be gentle and kind."
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I've been following his other posts; and my answer was based on his pattern. You have a pattern too.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I suggest that whenever your message includes the words "get off my lawn", you rather drop the the entire message.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
Thanks for the suggestion.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
mike7411 wrote: You want to store the following data about each user:
...
password
If that's the user's password for your application, then you most definitely don't want to store it! Instead, store a salted hash of the password, using multiple iterations of a cryptographically-secure one-way hashing algorithm:
Secure Password Authentication Explained Simply[^]
Salted Password Hashing - Doing it Right[^]
If it's the user's password for a third-party system, then you've got a much bigger problem to deal with. The data will need to be encrypted at rest, with appropriate controls in place to ensure that nobody other than the user who owns the record can access their plaintext password. You'll need a robust strategy for storing and rotating your encryption keys. You'll need comprehensive auditing of access to those keys. And probably a million other things I haven't thought of.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I already stated that he should store a hash value.
Nice to hear that you picked that up
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
I'm using Serilog. It seems way over-engineered to me, but I'm stuck with it. And, the docs arn't very helpful IMO.
My question is about log levels. For Serilog, there's documentation like this[^] and examples like this:
Log.Verbose("Here's a Verbose message.");
Log.Debug("Here's a Debug message. Only Public Properties (not fields) are shown on structured data. Structured data: {@sampleData}. Simple data: {simpleData}.", structuredData, simpleData);
Log.Information(new Exception("Exceptions can be put on all log levels"), "Here's an Info message.");
Log.Warning("Here's a Warning message.");
Log.Error(new Exception("This is an exception."), "Here's an Error message.");
Log.Fatal("Here's a Fatal message.");
Neither the docs nor the examples explain very well where/how you would actually use each of these levels.
For example, let's says I have this method:
private void DoSomeProcessing(string inputFile, bool someParam)
{
Log.Information("Inside DoSomeProcessing");
if (someParam)
{
Log.Warning("Just letting you know that 'someParam' = true");
}
if (string.IsNullOrEmpty(inputFile))
{
Log.Error("inputFile is null");
throw new ArgumentNullException(nameof(inputFile));
}
try
{
Log.Information("Doing the processing");
var a = 10 + 20;
Log.Information("Doing some more");
var b = 10 + a;
Log.Information("And even more");
var v = a + b;
}
catch (Exception e)
{
Log.Fatal("Something terrible happened here!");
throw e;
}
}
Exception logging I get, but is this how you would Info and Debug? Writing out lines all over the place?
Also, I have "MinimumLevel": "Debug" in my appsettings.json, yet all of these line get written out.
I'm guuessing I'm not understanding how to use it right. Can someone shed some light? Thanks
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|
They seem to explain it pretty well in the doc link you provided[^]:
Quote: The MinimumLevel configuration object provides for one of the log event levels to be specified as the minimum. In the example above, log events with level Debug and higher will be processed and ultimately written to the console.
(highlight is mine).
As a general strategy, I think you would probably have a setting somewhere that changes the minimum log level and you would come up with rules like:
- Verbose level is for all function enrty/exit points
- Debug level is for parameters and results
- Info level is for start/stop of big actions
and so on, and so on...
Mircea
|
|
|
|
|
The reality is that first, regardless of logging library, this is never clear in terms of practical programming.
Additionally keep in mind that a potential exists that different logging levels might impact execution flow.
There are three usage scenarios
- Production
- QA
- Developer
Some would claim that Error/Warn is only appropriate for Production. That however is simplistic and it will not work in non-trivial situations.
That is because for larger systems debugging production problems often requires looking at execution flow. So logging that represents the successful execution of code (trace logging.)
A perfect example of this is a job system or microservice (ms). In production the question will come up as to 'why' the job/request is not being handled. With logging one can see that the job/ms is actually running. Not just a specific requests, but all requests.
Then trace logging shows or doesn't show that a specific request was handled. And how it was handled.
Trace logging would use a log level of 'Info'. So Prod would use Error/Warn/Info.
The claim would (and will) be made that the log level 'Debug' allows one to turn something on in production for more information. But often that doesn't matter because the failure occurred yesterday, so attempting to figure it out today with more logging is seldom going to help.
The 'Debug' level is often used by developers because of this. But developers often do silly things like log only the index of a for variable. So no context just the value. Which makes sense when they are figuring out a problem but will make no sense and likely add a LOT of noise if you really do turn on 'Debug' in production.
Because of that then one must do code reviews to insure at least that Debug logging provides a context and does not cause significant (useless) noise.
All of that then comes back to QA. What should they run? If you actually want to allow Debug logging and it will be turned on in production then you then need to test both with it on and with it off. So testing twice. Both to insure there is not too much noise and that it does not interfere with functionality.
Due to all of that for me I limit all code check ins to Error/Warn/Info. And in practice I haven't even used Warn for a very long time.
Kevin Marois wrote: Exception logging I get, but is this how you would Info and Debug?
Pseudo code for a trace log entry.
Log.Info("CreateRequest: RequestId=<id> AssetId=<assetId> Result=<resultCode>");
And should you log an exception for Info? Yes.
As one example because the exception occurs at a non-critical place. For example if you are collecting metrics in a database like how long an operation took, you do NOT stop the execution flow if there is a database error. But you probably do want to log it.
Kevin Marois wrote: Can someone shed some light?
Also understand that developers and only developers are the target for logging.
There will be requests that Operations, Product Support (customer service) and/or QA 'need' to use it.
If so then those are product requirements. Those people need to create tickets (stories/epics) to specify exactly what they need.
And then QA needs to verify it.
You might or might not use your standard logging for this.
You might also get request from Customers. Such as 'Audit Logging' or 'User login logging'. Those are NEVER implemented using the logging system. Rather it is implemented solely and completely within the product just like any other feature.
|
|
|
|
|
Alright, I thought I'd take up a new hobby project, and use it to try and implement some ideas on domain-driven design. In essense, the project is to develop a "Rigging Designer", that allows civil engineers to define rigging needed to lift heavy objects. I'm struggling a bit with how to implement the ideas of DDD, hence this question.
The hierarchy of domain objects is:
- Lift - a lift operation
- LiftObject - the thing to lift
- Weight - weight of the object, double
- Cog - centre of gravity, position in X, Y, Z
- Liftpoint - point where you can attach rigging, can have up to four
- Id: Id, local to Lift
- Position: position in X, Y, Z
- Hook - a hook, can have up to two
- Position - X, Y, Z position of the hook
- Type: 1, 2, 3, 4 leg hook
- Leg - a leg between a hook, and a piece of rigging, can have up to 4 legs per hook
- Id - Id local to hook
- LiftPointId
The library / app will have two major components: designing consistent lifts (i.e. you can't connect two hooks to the same lift points), and solving them (i.e. calculating the load on legs and hooks).
Alright, that's it for domain knowledge. Now my question: what do I treat as aggregates, entities and value objects? The way I see it now:
- Lift is aggregate, since you can't modify any of the sub objects without needed to see if it is still consistent with the other ones (i.e. changing the cog changes the validity of the lift points). It's also an entity, since we want to be able to model multiple lifts.
- LiftObject is an entity, although I expect that it can never be referenced by more than one lift (since modifying this entity would have implications to all connected lifts)
- Weight and Cog are clear value objects
- Hook is a (local) entity
- Leg is a (local) entity
First question: am I implementing the ideas of DDD correctly.
Now, for my second question. I'll work on this project with a colleague, who will be implementing the solver. I intend to implement the following modules:
- Common - contains interfaces describing the models
- Designer - contains concrete implementations of the models in Common, used for creating and changing the models
- Solver - uses the interfaces in common to calculate the loads on the hooks and legs
Second question: I like the idea of defining interfaces (which are very short and readible) in the Common namespace, which allows me and him to work very independently. However, this means he can't depend on concrete implementations for his unittest, so he has to create mock implementations of the classes. Is this good practice, or just a lot of overhead?
|
|
|
|
|
There's a physical model and a logical model; I don't see you addressing the logic model. ("value objects"?)
You're creating interfaces, and unit tests, while the overall design is still incomplete, IMO. Wouldn't be able to "approve" your plan,
Just what I "see".
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
But MS says it better.
Quote:
... The issue with the MVVM pattern is that it can inadvertently lead to apps that have too many layers and too many allocations.
... But strict adherence to any variation of the pattern can lead to apps with a lot more overhead than can be justified.
... consider putting event handlers in your code-behind ....
MVVM and language performance tips - UWP applications | Microsoft Learn
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I'm shocked--shocked, I tell you--that MSFT would give a tinker's cuss for performance. For as long as I can remember, it doesn't matter what the hardware folks do to speed up CPUs or increase memory and disk space, because most of the software folks frivolously piss it away. I get the sense, admittedly somewhat superficially, that web-based applications in particular are absolute pigs in excrement when it comes to performance. Does performance still even matter?! If it does, and I wasn't retired, I'd be sorely tempted to find and work with folks who were aiming to blow all of this crapola out of the water.
|
|
|
|
|
Greg Utas wrote: Does performance still even matter?...If it does, and I wasn't retired
It really mattered in the 50/60s whether you used a bubble sort or a binary sort.
For the single application that one would write then.
Now companies do enterprise systems which can contain thousands or even tens of thousands of running instances which have far more serious issues with performance. None of which can be solved with tuning individual lines of code.
Complexity of course drives that. There are many, many other factors that also impact it.
As an example I once increased performance by about 60000% (10 hours to less than 1 minute) by changing requirements. Doubt increasing the CPU by 3% would have had that much impact.
On the other hand I have seen developers spending more than a week 'optimizing' code which would have no impact at all on the user experience.
Not to mention of course business practices that allowed customers to abuse the enterprise to such an extent (by not forcing them to pay for what they were using) that they then started complaining that the system was too slow.
Customers like to complain about performance but often can't even cite what that actually means. And it is very seldom that they are willing to switch product/services because of that. It is the other features that they need/want which drive their decision. Not to mention the cost.
|
|
|
|
|
I agree that optimizing the code is unlikely to help here. The problem is the high-level design, like how the many thousands of instances are supported. The mania for stateless servers that must continually recreate context is another problem.
Poor performance in these types of soft real-time systems usually means one of two things:
1. The response time annoys users.
2. A lot more must be spent on computing equipment than in a system that is better designed.
|
|
|
|
|
So, their "best practice" isn't exactly best practice for performance reasons? Color me "shocked."
|
|
|
|
|
Using a pattern, on purpose, that obscures the power and potential of the platform is beyond not making sense.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Gerry Schmitz wrote: MVVM pattern is that it can inadvertently lead to apps that have too many layers and too many allocations.
Remind me again which pattern is it exactly that guarantees that can't happen?
|
|
|
|
|
You're talking wrappers, frameworks and methodologies (MVVM). A "pattern" can be a simple plug-in that "adds" functionality instead of masking or contorting it.
MVVM is a "bunch" of patterns; all directed to "indirection".
A simple statement like: NO code behind ... is a pattern (of behaviour).
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Ok. But I don't see how that answers my question?
|
|
|
|
|
Quote: Ok. But I don't see how that answers my question?
I gave you an example: a plug-in. Where are the "layers" and "allocations"? One function reference. Are you saying a plug-in is not a pattern? What is a "door"?
Your "argument" is all patterns are "faulty". Back it up.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|