BlazingSolutions / TimeKeeper

A project for learning Blazor
9 stars 0 forks source link

Readme (for each branch) #42

Closed harperjohn closed 3 years ago

harperjohn commented 3 years ago

I think that our project needs a Readme file that explains the steps needed to build and run the application for both a completely clean git clone to a new directory, and to an existing directory after major refactoring has taken place.

I really like that we have multiple branches (simplified, vertical slices, etc) I think this is a great idea!

But I think we need to address this in the readme too...

For example, once I get one of the branches working and I want to try another branch, what do I do? Do I need a database for each branch? If not how is that handled.

I am still having trouble getting the first application to run... and I have to admit, that it is probably due to "operator error" on my part because I usually use Sqlite (when I use a database). I am a good test for the "new to SQL Server" perspective.

If the database actions can't be automatically scripted in the build, or managed by the running app, I think we need some explicit instructions that allow a new user/contributor to get the project built and running "out of the box".

adamfoneil commented 3 years ago

My thoughts on this are a bit adjacent to your issue. I agree a nice readme is in order on getting the db setup. For some context, here's my take on this in one of my own projects.

RE this repo, I didn't know how to create the initial database, either. I know people typically use EF Migrations for this. Being somewhat contrarian/allergic to that, I'd like to do a demo with ModelSync in the next little bit. Yes, this is an entirely custom tool (open source), and with no community credibility. I'm even selling licenses for it, but I would give everyone currently in the Blazing Saddles team a free key. But I would want to do a video walktrhough first. It would still be optional in the end, although it would involve adding a custom build event to the repo.

My main issue with migrations is the chilling effect they have on iteration. Database development often requires a lot of incremental changes that come to mind haphazardly. Having to stop and write a migration for every single change brings a lot of mentally taxing context switching. In my day job, this accumulates so much friction that we do a lot of migration avoidance, trying to re-purpose existing tables for uses they weren't meant for, or dreading the process when it's unavoidable. Because migrations are order-sensitive, migrations started in different branches at the same time will fail when merged into the main branch (because the preceding migration will be different after a source merge). So, we end up having to delete and re-create migrations manually to do a successful deployment.

On the up side, migrations really do enable multi-user database collaboration on disconnected databases, and they are effectively an "industry standard." My tool ModelSync is really optimal in a single user or shared dev database scenario, which is controversial for its own reasons. Basically, with ModelSync, if you add or change a model class, it generates a SQL script of the diff between your assembly and the target database. It executes the SQL -- with very little friction or context switching from the core dev flow in Visual Studio. The diff algorithm is pretty nifty IM biased O though not perfect for every change scenario you'll come across, but I find it plenty good enough for what I do.

jonhilt commented 3 years ago

I'm loving these discussions gang! It's great to be able to throw ideas around in an environment where we're not under pressure to actually deliver something important :-)

I'm pretty comfortable with EF Core's migrations but that could well be because I tend to go Domain/model first, then just use the EF Core tools (via the .NET CLI) to automatically generate the migrations.

From this perspective I've not felt that this hindered iteration, but I do accept that they are not perfect and everyone's mileage may vary.

I am hesitant to make this project rely on something which isn't free and easily accessible to all contributors. For much the same reasons as I would like to avoid insisting everyone use Visual Studio, it can quickly make the project less accessible to anyone who wants to just download it and have a go.

Regarding a readme, along the same lines, I feel it's important that the project just works when you download the source. A Readme is definitely useful to nudge people in the right direction, but it's also important that there aren't lots of set up steps required to make it work.

jonhilt commented 3 years ago

Regarding your specific issue @harperjohn I think I've found the problem.

If you grab the refit-spike branch and try running that I think you'll find it works better. I've updated the Properties\launchsettings.json files in all three projects (Api, Client and Server) to specify different URLs (well specifically ports) for the various projects when launching them via the ASP.NET Core development server.

They were all set to 5000/5001 before.

This does raise a separate issue about making sure the clients point to the Web API whether it's being served via IIS or the built-in ASP.NET development server. For now you may need to check the URLs in program.cs (client project) or startup.cs (server project) as they could be pointing to the wrong address for the API.

DotNetDublin commented 3 years ago

Great suggestions and it was on the list I keep in my own head to put together a getting started guide similar to what @adamfoneil suggested and have it as part of the read me that is included in the project repository

As @jonhilt stated it should be restricted to a few simple steps.

If someone is making an update that would impact theses instructions it should be mentioned in the pull request and they should update the read me file accordingly. As the application develops I would imagine it would be a pretty rare occurrence that the getting started instructions would need to be updated.

adamfoneil commented 3 years ago

I'm happy just saying my peace on the matter :-) Agree a custom tool/build process is a tough sell! It's very likely I need more practice with migrations or just to see them in a different project.

DotNetDublin commented 3 years ago

Managing database migrations is an interesting topic and I was watching a Tim Corey video on Entity Framework and this was one area he said he didn't like about Entity Framework as he felt applying changes to the database schema is something that should be left to a senior developer. I'm paraphrasing from memory however I can appreciate his point.

In terms of how I approached the database with Time Keeper I actually went down the road of database first, rather than code first.

Why did I do this you ask? Well, my brain is wired to create the database tables first and I had created four tables before I remembered that with entity framework it is more common to go the code first route. Rather than backtrack I finished creating the tables manually within the SQL Server Project in Visual Studio and then referenced this article https://www.yogihosting.com/database-first-approach-entity-framework-core/

The overall process turned out to be

  1. Create tables or add columns, stored procedures, views etc within the SQL Server Project TimeKeeper.Database.

  2. Publish the changes by selecting to publish the TimeKeeper.Database.

When selecting to publish you are presented with some options including "Publish" and "Generate Script".

Publish

Publish will go ahead and make the necessary changes to the database.

Generate script will script the changes so that they can be applied manually which is useful if you want to review what it's going to do or need to pass it to someone for review.

If the TimeKeeper database already exists it will only apply the necessary changes, if it doesn't exist it will create the database for you.

  1. Run the below command within the package manager console setting the default project to be TimeKeeper.Database to create the models.
PM> Scaffold-DbContext "Server=MyServer;Database=TimeKeeper;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

If the change is minor such as adding a column you could always just manually adjust the appropriate model.

DotNetDublin commented 3 years ago

I'm happy just saying my peace on the matter :-) Agree a custom tool/build process is a tough sell! It's very likely I need more practice with migrations or just to see them in a different project.

Hi @adamfoneil. Would agree with @jonhilt in terms of keeping the tooling we use as accessible and main stream as possible however I think it's great to highlight work done by members of our community. Therefore if we have instructions on how to manage the database migrations it would be good to end with something like the below.

Our contributor @adamfoneil has a great tool for managing ... you may want to consider this for your own projects.

I think if I had published some software or had a nuget package I would mention it every five minutes on average :)

harperjohn commented 3 years ago

@adamfoneil Yes - I agree with the others, that we should aim to keep the project as dependency free as possible.

But I have to say that your note completely echoed, amplified and extended the "spirit" of my original note.

Your "take" at https://github.com/adamfoneil/BlazorAO/wiki/Getting-Started is a great example, and this sentence nails is:

If it's hard to get started with this app, then it would turn most everyone away.

So even if we don't use your tool, I would be glad to see the instructional video and a branch that demonstrates it.

DotNetDublin commented 3 years ago

I've just pushed a first draft of a read me which now appears at https://github.com/BlazingSaddlesSolutions/TimeKeeper

It includes a "Getting Started" section however it's not complete as I want to include sections on how you can select whether to run the Client and/or the Server project alongside the API and I also want to examine @jonhilt comments on the localhost ports and how they may have caused the issue you faced.

I have some settings already coming from configuration files however we need any reference to localhost not to be hardcoded.

That said I'm wary of going into too much detail on the getting started section at the moment until we've settled on a project architecture and method for database migrations as that will have an impact.

ripteqdavid commented 3 years ago

Agree with all above. We should keep the project as vanilla as possible.

However, I love what you've done @adamfoneil as this mirrors how I work. Given my history, I'm much more comfortable designing and working with databases directly in SQL Server Management Studio. I generally use Redgates SQL Tools to generate both schema and data diff scripts that gets pushed to production. I've written a small tool that generates model classes (POCO) using templates (so you can vary the output by your desire (eg. plain poco, or poco with INotify etc.), and can be generated at any time.

MilesGibson commented 3 years ago

Hi All,

FWIW, here is my 2 cents on the matter. I am a data modeler first, developer second. Everything I do is Database First. I use DevArt’s Entity Developer to generate my entire data access layer, including generic repository code, data annotations, validations etc. When I make a change to the schema (usually in xCase or SSMS), I just run ED against the schema and bam! All of the plumbing is re-generated. Clean and simple. I often have several projects that use the same schema, so I created a separate .NET Standard project for the DAL, and then just include it in my solution. I don’t have to hunt for a model/entity class, modify it manually and then migrate it back to the database. POtato-PotAto?

That is not to say that Code First doesn’t work – but I feel that going with Database First will mean a better designed database architecture. And I use Red-Gates SQL Compare to synch between dev/test and production.

Cheers,

Miles

DotNetDublin commented 3 years ago

Thanks for sharing @MilesGibson. It's been really interesting to hear how everyone approaches this.