In order to customize the latter one and add another step tidy_storage, you’d normally have to subclass all three activities and override steps.
- Feb 2021
-
trailblazer.to trailblazer.toTrailblazer30
-
-
step :policy, before: :create_model
-
the validate task gets removed, assuming the Admin won’t need a validation
-
magnetic_to: :paypal
-
step Subprocess(Memo::Validate), Output(:invalid_params) => Track(:failure)
-
While you could nest an activity into another manually, the Subprocess macro will come in handy.
-
The macro automatically wires all of Validate’s ends to the known counter-part tracks.
-
Output() in combination with Path() allow very simple modelling for alternive routes.
-
Note that the path ends in its very own end, signalizing a new end state, or outcome. The end’s semantic is :with_cc.
-
Since notify sits on the “failure” track and hence is “magnetic to” :failure, find_provider will be connected to it.
-
The Track() function will snap the output to the next task that is “magnetic to” the track’s semantic.
-
This connects the failure output to the previous task, which might create an infinity loop and waste your computing time - it is solely here for demonstrational purposes.
-
step :charge_creditcard, Output(:failure) => End(:declined)
-
Adding ends to an activity is a beautiful way to communicate more than two outcomes to the outer world without having to use a state field in the ctx. It also allows wiring those outcomes to different tracks in the container activity.
-
step :charge_creditcard, Output(:failure) => End(:success) end This reconnects both outputs to the same end, always ending in a - desirable, yet unrealistic - successful state.
-
step :find_provider, Output(UsePaypal, :paypal) => Track(:paypal)
-
The DSL will, per default, wrap every task with the Binary interface, meaning returning true will result in Activity::Right, and false in Activity::Left.
-
Currently, only Right signals are wired up.
-
Activity::Left
Needs to be
Trailblazer::Activity::Left
-
Note that you can return either a boolean value or a [signal subclass] in order to dictate the direction of flow.
-
-
allowing you to limit what invoked tasks or nested activies “see” and what they propagate to the caller context.
-
Please note that the actual task doesn’t have to be a proc! Use a class, constant, object, as long as it exposes a #call method it will flow.
-
You may use keyword arguments in your filters for type safety and better readable code.
-
In both filters, you’re able to rename and coerce variables. This gives you a bit more control than the simpler DSL.
-
Trailblazer will automatically create a new Context object around your custom input hash. You can write to that without interferring with the original context.
-
a method that doesn’t have access to variables outside its scope
-
As usual, you may provide your own code for dynamic filtering or renaming.
-
Please note that I/O works for both “simple” tasks as well as nested activities.
-
An array value such as [:params] passed to :input will result in the configured task only “seeing” the provided list of variables. All other values are not available, mimicking a whitelist.
Tags
- good abstraction
- expressive
- ruby: keyword arguments
- DSL
- funny
- type safety
- interesting idea
- flexibility
- terminus/end event
- non-binary
- makes sense to me
- information hiding
- strange words/terms/names
- ruby: callable object
- immutable data
- unintuitive
- elegant solution
- typo
- applies/works in all cases/subcases (polymorphism) (no arbitrary limitation)
- scope (programming)
- simple
- annotation meta: may need new tag
- allowlist
- example: in order to keep example concise/focused, may not implement all best practices (illustrates one thing only)
- readability
- macro
- good example
- what does this actually mean?
- trailblazer-activity
- having enough control over something
- inheritance (programming)
- interchangeable
- railway-oriented programming
- automatic
- leverage library/tool to do something for you
- polymorphism
Annotators
URL
-
-
github.com github.com
-
Licensed under the LGPLv3 license. We also offer a commercial-friendly license.
-
With Activity, modeling business processes turns out to be ridiculously simple: You define what should happen and when, and Trailblazer makes sure that it happens.
-
-
github.com github.com
-
Version HEAD now
-
Tree Navigation
-
-
github.com github.com
-
For that matter, why not remove the dependency on jQuery entirely (#111)?
-
Sure, zero-config one-click installs are nice and all, but:
-
-
Personally, I'm starting to think that the feature where it automatically adds xray.js to the document is more trouble than it's worth. I propose that we remove that automatic feature and just make it part of the install instructions that you need to add this line to your template/layout: <%= javascript_include_tag 'xray', nonce: true if Rails.env.development? %>
-
-
github.com github.com
-
Now that I've thought more about it, I honestly think the auto-adding the script feature is overrated, over-complicated, and error-prone (#98, #100), and I propose we just remove it (#110).
-
-
github.com github.com
-
now that I've thought more about it, I think the auto-adding the script feature is overrated, over-complicated, and error-prone (#100), and ought to just be removed (#110).
-
-
github.com github.com
-
now that I realize how easy it is to just manually include this in my app: <%= javascript_include_tag 'xray', nonce: true if Rails.env.development? %> I regret even wasting my time getting it to automatically look for and add a nonce to the auto-injected xray.js script
-
Wasted too much time getting it to work with old Rubies/Rails, when I think the correct path should be to just remove support for them going forward
-
Open a separate PR to add Rails 6 to the CI matrix
-
I'm not very familiar with this feature. Do you know what version of Rails is required for this code to work? Is it Rails 6.0+? We run the test suite via Travis CI for many versions of Rails so I am concerned that this will cause test failures on older versions. Can we write the tests so that they gracefully exclude the CSP stuff on older versions where CSP is not supported?
-
(match = html.match(/<meta name="csp-nonce" content="([^"]*)"/)) && match[1] html[/<meta name="csp-nonce" content="([^"]*)"/, 1]
-
Non-blocking suggestion: This is a little more elegant, if you prefer this syntax:
-
This is failing CI because CI is testing against Rails < 6. I think the appropriate next steps are: Open a separate PR to add Rails 6 to the CI matrix Update this PR to only run CSP-related test code for Rails >= 6.0.0 Can you help with either or both of those?
Tags
- regret
- removing features to simplify implementation
- wasted effort
- backwards compatible
- concise
- elegant code
- Ruby
- removing feature that is more trouble than it's worth (not worth the effort to continue to maintain / fix bugs caused by keeping it)
- maintainer wants/prefers separate smaller pull requests
- removing legacy/deprecated things
- pull requests: can't just throw it over the fence and be done (requires follow-through)
- build/testing matrix (CI)
- fix design/API mistakes as early as you can (since it will be more difficult to correct it and make a breaking change later)
- non-blocking suggestion
Annotators
URL
-
-
travis-ci.com travis-ci.com
-
Maintaining the builds of your repositories should be everyone’s job. Instead of relying on that one build person in the team, Travis CI makes infrastructure and configuration a team responsibility.
-
-
docs.travis-ci.com docs.travis-ci.com
-
CI=true
-
-
github.com github.com
-
Rebasing For feature/topic branches, you should always use the --rebase flag to git pull, or if you are usually handling many temporary "to be in a github pull request" branches, run the following to automate this: git config branch.autosetuprebase local
That's what I keep telling people. Glad to see I'm not the only one...
Tags
Annotators
URL
-
-
www.schneems.com www.schneems.com
-
While I certainly don’t think that all configuration should be “self hosted” in this kind of way
how is it "self hosted"? in what way?
I think I found the answer here https://github.com/rails/sprockets/blob/master/UPGRADING.md:
One benefit of using a
manifest.js
file for this type of configuration is that now Sprockets is using Sprockets to understand what files need to be generated instead of a non-portable framework-specific interface.So it is "self-hosted" in that Sprockets is using Sprockets itself for this...?
-
-
That’s it. If you have a previous “precompile” array, in your app config, it will continue to work. For continuity sake I recommend moving over those declarations to your manifest.js file so that it will be consistent.
-
programmers can try to be aware of their configuration systems and the cognitive overhead they impose on people.
-
As we know, naming is hard.
-
Another thing I don’t like is the name of the config file manifest.js. Internally Sprockets has the concept of a manifest already Sprockets::Manifest, but the two aren’t directly coupled. We also already have a “manifest” JSON file that gets generated in public/assets/ and has manifest in the name .Sprockets-manifest-140998229eec5a9a5802b31d0ef6ed25.json. I know one is a JS file and one is a JSON file, but it’s a bit confusing to talk about.
When I first heard of app/assets/config/manifest.js, I was a bit confused too, and assumed/wondered if it was related to the manifest it generates under
public
. -
The name makes me think of “The Legend of Zelda”. I imagine the original Sprockets author saying “It’s dangerous to go alone” and then handing me a javascript file.
-
The link name is not very helpful, it doesn’t explain what it does very well.
-
Instead of having this confusing maze of lambdas, regexes, and strings, we could, in theory, introduce a single entry point of configuration for Sprockets to use, and in that file declare all assets we wanted to compile. Well, that’s exactly what the manifest.js file is.
-
I guess in short you could say that I don’t like this interface very much.
-
Another big issue is that the config wasn’t really expressive enough. From the beginning Rails needed a way to say “only compile application.css and application.js, but compile ALL images” by default. With our previous interface, we’re limited to only strings.
-
That’s pretty gnarly. While the name of the constant LOOSE_APP_ASSETS gives me some idea of what it does, it still takes a second to wrap your mind around. If you were trying to figure out what assets are being precompiled and you did a puts config.assets.precompile that lambda object would be utterly baffling.
-
Another thing I don’t like: our asset behavior is decoupled from the assets. If you’re mucking around in your app/assets folder, then you have to first know that such a config exists, and then hunt it down in a totally different config folder. It would be nice if, while we’re working in asset land, we didn’t have to mentally jump around.
-
For example, what if your site has a customer interface and an “admin” interface? If the two have totally different designs and features, then it might be considerable overhead to ship the entirety of the admin interface to every customer on the regular site.
-
Before we get into what the manifest.js does, let’s look at what it is replacing.
-
When Sprockets was introduced, one of the opinions that it held strongly, is that assets such as CSS and JS should be bundled together and served in one file.
-
The alternative was to have multiple scripts or stylesheet links on one page, which would trigger multiple HTTP requests. Multiple requests mean multiple connection handshakes for each link “hey, I want some data”, “okay, I have the data”, “alright I heard that you have the data, give it to me” (SYN, ACK, SYNACK). Even once the connection is created there is a feature of TCP called TCP slow start that will throttle the speed of the data being sent at the beginning of a request to a slower speed than the end of the request. All of this means transferring one large request is faster than transferring the same data split up into several smaller requests.
-
One way to alleviate this configuration fatigue is by making configuration consistent and composable. That’s what Sprocket’s new “manifest.js” seeks to do.
-
Have you ever felt like a framework was getting in the way instead of helping you go faster? Maybe you’re stuck on some simple task that would be easy to do manually, but your framework is making you jump through configuration hoops. I end up getting lost in a sea of documentation (or no documentation), and the search for that one magical config key takes just a tad bit too long. It’s a productivity sink, and worse than the time delay it adds to my frustration throughout the day.
-
When I hit ETOOMUCHFRUSTRATION, then I’m definitely fighting the framework.
Tags
- naming things is hard
- network performance
- configuration
- gamer humor
- fast load times (web pages)
- inconsistent
- cognitive load
- TCP
- messy
- use meaningful names (programming)
- what a mess
- switching/migrating to something different
- sprockets
- I agree
- code organization: co-location
- newer/better ways of doing things
- discoverability: not easily discoverable
- compatibility
- hard to understand
- programmer humor
- bad combination/mixture/hybrid/frankenstein
- design goals
- not expressive enough
- wasteful/inefficient use of resources
- naming
- external assets: one larger file vs. multiple smaller files (HTTP requests)
- co-location: not co-located
- strong opinions
- Sprockets: manifest.js
- self-explanatory
- poor interface
- consistent
- the specific context is important
- library/framework getting in the way more than helping you
- intention-revealing
- overhead
- illustrating problem before showing solution
- self-documenting
- not:
- fast startup times
- what does this actually mean?
- what is the alternative?
- hard to follow/read/understand
- composability
- confusing
- general solution
Annotators
URL
-
-
sass-lang.com sass-lang.com
-
Local variables can even be declared with the same name as a global variable. If this happens, there are actually two different variables with the same name: one local and one global. This helps ensure that an author writing a local variable doesn’t accidentally change the value of a global variable they aren’t even aware of.
-
Sass variables, like all Sass identifiers, treat hyphens and underscores as identical. This means that $font-size and $font_size both refer to the same variable. This is a historical holdover from the very early days of Sass, when it only allowed underscores in identifier names. Once Sass added support for hyphens to match CSS’s syntax, the two were made equivalent to make migration easier.
-
-
github.com github.com
-
echo "firefox hold" | sudo dpkg --set-selections
-
-
docs.travis-ci.com docs.travis-ci.com
-
A build matrix is made up by several multiple jobs that run in parallel.
-
-
github.com github.com
-
As a workaround, I guess I'll have to disable my strict CSP in development, but I'd prefer to keep it strict in development as well so that I ran into any CSP issues sooner...
-
-
forum.wordreference.com forum.wordreference.com
-
At work, we often mention "throwing something over the fence" and "wrong rock" so there is (to us) a proverbial fence and a proverbial wrong rock.
-
-
www.chemistryworld.com www.chemistryworld.com
-
Those things are someone else’s job, not ours, you know.
-
-
-
github.com github.com
-
Ruby on Rails 6 Note:: With the release of Rails 6 there have been some minor changes made to the default configuration for The Asset Pipeline. In specific, by default Sprockets no longer processes JavaScript and instead Webpack is set as the default. The twbs/bootstrap-rubygem is for use with Sprockets not Webpack.
Tags
Annotators
URL
-
-
github.com github.com
-
-
Eyeglass provides a way to distribute Sass files and their associated assets and javascript extensions via npm such that any build system can be adapted to automatically expose those Sass files to Sass's @import directive by just installing the code.
-
This project is provided by the LinkedIn Presentation Infrastructure team as open source software
-
-
github.com github.com
-
Keeping bootstrap-sass in sync with upstream changes from Bootstrap used to be an error prone and time consuming manual process. With Bootstrap 3 we have introduced a converter that automates this.
-
Do not use *= require in Sass or your other stylesheets will not be able to access the Bootstrap mixins or variables.
-
-
github.com github.com
-
It's recommended to configure this library by setting environment variables.
-
-
github.com github.com
-
STATSD_SAMPLE_RATE: (default: 1.0)
It's recommended to configure this library by setting environment variables.
The thing I don't like about configuration via environment variables is that everything is limited/reduced to the string type. You can't even use simple numeric types, let alone nice rich value objects like you could if configuration were done in the native language (Ruby).
If you try to, you get:
ENV['STATSD_SAMPLE_RATE'] = 1 config/initializers/statsd.rb:8:in `[]=': no implicit conversion of Integer into String (TypeError)
-
This version makes the new client that was added in version 2.6+ the default client, and removes the legacy client. All previously deprecated functionality has been removed (since version 2.5, see below).
-
-
guides.rubyonrails.org guides.rubyonrails.org
-
Keep in mind that third party code with references to other files also processed by the asset Pipeline (images, stylesheets, etc.), will need to be rewritten to use helpers like asset_path.
-
vendor/assets is for assets that are owned by outside entities, such as code for JavaScript plugins and CSS frameworks.
-
-
speakerdeck.com speakerdeck.com
-
How Sprockets works
-
-
github.com github.com
-
Some assets will be compiled as top-level assets when they are referenced from inside of another asset. For example, the asset_url erb helper will automatically link assets:
-
but if you were previously using regexp or proc values, they won't work at all with Sprockets 4, and if you try you'll get an exception raised that looks like NoMethodError: undefined method 'start_with?'
-
To correct this, you can move these files to some subdirectory of ./app/assets/stylesheets or javascripts; or you can change the manifest.js to be more like how Rails with Sprockets 3 works, linking only the specific application files as top-level targets
-
When compiling assets with Sprockets, Sprockets needs to decide which top-level targets to compile, usually application.css, application.js, and images.
-
Here's the last issue where source maps were discussed before the beta release.
-
How do you know if source maps are working correctly? Try adding a syntax error to one of your assets and use the console to debug. Does it show the correct file and source location? Or does it reference the top level application.js file?
-
Source maps eliminate the need to serve these separate files. Instead, a special source map file can be read by the browser to help it understand how to unpack your assets. It "maps" the current, modified asset to its "source" so you can view the source when debugging. This way you can serve assets in development in the exact same way as in production.
-
Source maps are a major new feature.
-
Your Rails app Gemfile may have a line requiring sass-rails 5.0: gem 'sass-rails', '~> 5.0' # or gem 'sass-rails', '~> 5' These will prevent upgrade to sprockets 4, if you'd like to upgrade to sprockets 4 change to: gem 'sass-rails', '>= 5'
-
Sprockets 3 was a compatibility release to bridge Sprockets 4, and many deprecated things have been removed in version 4.
Tags
- prefer simpler option
- allowing sufficient time for discussion/feedback/debate before a final decision is made
- bundlers: top-level targets
- new feature
- external assets: one larger file vs. multiple smaller files (HTTP requests)
- Sprockets: manifest.js
- test plan / how to test (software development)
- source maps
- removing legacy/deprecated things
- workaround
- mapping
- sprockets
- compatibility
- have discussion/feedback/debate in public (transparency)
- how to check/verify/test whether something is working
- simplicity by design
- link to what you are referring to
- Gemfile: version constraints
- automatic
- dependencies: locking to specific version
Annotators
URL
-
-
www.lambdatest.com www.lambdatest.com
-
every human has a defined cognitive load that the memory can process. Making anyone process more information than defined will result in cognitive overloading.
-
-
en.wikipedia.org en.wikipedia.org
Tags
Annotators
URL
-
-
travis-ci.org travis-ci.org
-
Please be aware travis-ci.org will be shutting down in several weeks, with all accounts migrating to travis-ci.com.
-
Testing your open source projects will always be free! Seriously. Always. We like to think of it as our way of giving back to a community that connects so many people.
-
-
www.schneems.com www.schneems.com
-
TravisCI.org is dead.
-
-
stackoverflow.com stackoverflow.com
-
trailblazer.to trailblazer.to
-
So, whenever you hear the medieval argument “Trailblazer is just a nasty DSL!”, forgive your opponent, you now know better. The entire framework is based on small, clean Ruby structures that can be executed programmatically.
-
The entire framework is based on small, clean Ruby structures that can be executed programmatically.
-
-
trailblazer.to trailblazer.toTrailblazer14
-
Yes, we could and should use Reform or Dry-validation here.
-
a task in an activity can be any callable Ruby object
-
-
Each step receives the return value of its predecessor. The return value decides about what next step is called.
-
In order to invoke, or run
-
the ability to “error out” when something goes wrong
-
Six lines of code create an executable object that, when invoked, will run your code in the order as visible in our diagram, plus the ability to “error out” when something goes wrong.
-
While you could program this little piece of logic and flow yourself using a bunch of Ruby methods along with a considerable amount of ifs and elses, and maybe elsif, if you’re feeling fancy, a Trailblazer activity provides you a simple API for creating such flow without having to write and maintain any control code. It is an abstraction.
-
keeps a semantic
-
A task is often called step.
-
Your actual logic happens in tasks, the labeled boxes. A task may be any callable Ruby object, an instance method or even another activity.
-
Every path or flow stops in a terminus event. Those are the filled circles. Often, we call them end event, too!
-
The “error path” or “failure track” is the lower path going the the failure terminus.
-
The “happy path” or “success track” is the straight path from start to the terminus named success.
Tags
- good abstraction
- different names for the same/identical thing (synonyms)
- control flow
- happy path / success track
- good explanation
- happy path
- terminus/termini
- ruby: callable object
- good tutorial
- example
- powerful
- typo
- error path / failure track
- example: in order to keep example concise/focused, may not implement all best practices (illustrates one thing only)
- abstractions
- tutorial
- error/exception handling
- too many ifs: bad
- terminology
- what does this actually mean?
- reduce/minimize/simplify/remove control flow code
- programming: invoke/run/call
- Trailblazer
- interchangeable
- railway-oriented programming
- polymorphism
Annotators
URL
-
-
www.theregister.com www.theregister.com
-
-
Redmond suggests nuking 'profanity, geopolitical, diversity' terms from browser source
-
Allowlist, not whitelist. Blocklist, not blacklist. Goodbye, wtf. Microsoft scans Chromium code, lops off offensive words
-
a proposal to cleanse the open-source code of "potentially offensive terms."
-
a suggestion by Microsoft to “cleanup of potentially offensive terms in codebase” aims to rid the software blueprints of language such as whitelist (change to allowlist), blacklist (change to blocklist), “offensive terms using ‘wtf’ as protocol messages,” and other infelicities.
-
In May, Microsoft announced AI features in Word that, among other features, will emit “advice on more concise and inclusive language such as ‘police officer’ instead of ‘policeman.’"
-
-
github.com github.com
-
-
Good intentions, but I doubt there's any relation of the origin of the terms blacklist/whitelist to race. There are many idioms and phrases in the English language that make use of colours without any racial backstories. I haven't met any black person (myself included) who was ever offended by the use of "blacklist".
-
Regardless of origin, allow/deny are simply clearer terms that does not require tracing the history of black/white as representations of that meaning. We can simply use the meaning directly.
-
Frankly, a good number find it patronising to make this kind of change.
-
-
en.wikipedia.org en.wikipedia.org
-
in functional programming, the terms "conditional expression" or "conditional construct" are preferred, because these terms all have distinct meanings
-
-
-
en.wikipedia.org en.wikipedia.org
-
The forms of the final keyword vary:
-
found that using only the Pascal-provided control structures, the correct solution was given by only 20% of the subjects, while no subject wrote incorrect code for this problem if allowed to write a return from the middle of a loop.
-
What Böhm and Jacopini's article showed was that all programs could be goto-free.
-
That such minimalism is possible does not mean that it is necessarily desirable
-
computers theoretically need only one machine instruction (subtract one number from another and branch if the result is negative)
-
-
sobolevn.me sobolevn.me
-
Literally, everything in this example can go wrong. Here’s an incomplete list of all possible errors that might occur: Your network might be down, so request won’t happen at all The server might be down The server might be too busy and you will face a timeout The server might require an authentication API endpoint might not exist The user might not exist You might not have enough permissions to view it The server might fail with an internal error while processing your request The server might return an invalid or corrupted response The server might return invalid json, so the parsing will fail And the list goes on and on! There are so maybe potential problems with these three lines of code, that it is easier to say that it only accidentally works. And normally it fails with the exception.
-
Return None. That’s evil too! You either will end up with if something is not None: on almost every line and global pollution of your logic by type-checking conditionals, or will suffer from TypeError every day. Not a pleasant choice.
-
Let’s start with the same number dividing example, which returns 0 when the error happens. Maybe instead we can indicate that the result was not successful without any explicit numerical value?
-
And we can specify types of wrapped values in a function return annotation, for example Result[float, ZeroDivisionError] returns either Success[float] or Failure[ZeroDivisionError].
-
Now you can easily spot them! The rule is: if you see a Result it means that this function can throw an exception. And you even know its type in advance.
-
we also wrap them in Failure to solve the second problem: spotting potential exceptions is hard
-
exceptions are not exceptional, they represent expectable problems
-
You can use container values, that wraps actual success or error value into a thin wrapper with utility methods to work with this value. That’s exactly why we have created @dry-python/returns project. So you can make your functions return something meaningful, typed, and safe.
-
Write special-case classes. For example, you will have User base class with multiple error-subclasses like UserNotFound(User) and MissingUser(User). It might be used for some specific situations, like AnonymousUser in django, but it is not possible to wrap all your possible errors in special-case classes. It will require too much work from a developer. And over-complicate your domain model.
-
Exceptions are not exceptional
-
Exceptions are just like notorious goto statements that torn the fabric of our programs.
-
Not all cases can be covered and easily restored. And sometimes when we will reuse this function for different use-cases we will find out that it requires different restore logic.
-
But why do we return 0? Why not 1? Why not None? And while None in most cases is as bad (or even worse) than the exceptions, turns out we should heavily rely on business logic and use-cases of this function.
-
And checked exceptions won’t be supported in the nearest future.
-
Almost everything in python can fail with different types of exceptions: division, function calls, int, str, generators, iterables in for loops, attribute access, key access, even raise something() itself may fail. I am not even covering IO operations here. And checked exceptions won’t be supported in the nearest future.
-
You still need to have a solid experience to spot these potential problems in a perfectly readable and typed code.
-
So, despite your code is type safe it is not safe to be used.
-
print will never be actually executed. Because 1 / 0 is an impossible operation and ZeroDivisionError will be raised.
-
So, the sad conclusion is: all problems must be resolved individually depending on a specific usage context. There’s no silver bullet to resolve all ZeroDivisionErrors once and for all. And again, I am not even covering complex IO flows with retry policies and expotential timeouts.
Tags
- anticipating what could go wrong / error/exception cases
- traditional exception handling (try/catch; begin/rescue)
- type safety
- accidentally works
- surprising
- can't support everything / all cases
- type checking
- why?
- depends on use case / application
- can't think of everything
- difficult/hard problem
- error/exception handling
- easy to see/notice
- good example
- Python
- special cases
- railway-oriented programming
- exceptions are expectable, not exceptional
- safety (programming)
- actually consider / think about how it _should_ (ideally) be
- monad: monadic value (wrapping a value within the monad)
- checked exceptions
- type annotations
- programming: goto
- the benefit of experience
- error/exception handling: spotting potential exceptions is hard
- the specific context is important
- sad/unfortunate conclusion
- key point
- exceptions that are not exceptional
- not:
- too many ifs: bad
- analogy
- monad: Either
- need to solve specific case/problems individually (there is no general solution)
- easy to miss / not notice (attention)
- seemingly contradictory
- type checking: type annotations (unchecked; in comments)
- rule of thumb
Annotators
URL
-
-
fsharpforfunandprofit.com fsharpforfunandprofit.com
-
(when used thoughtlessly)
-
-
-
github.com github.com
-
Or you can use Maybe container! It consists of Some and Nothing types, representing existing state and empty (instead of None) state respectively.
-
So, what can we do to check for None in our programs? You can use builtin Optional type and write a lot of if some is not None: conditions. But, having null checks here and there makes your code unreadable.
-
But now, you can do the same thing in functional style!
-
Brings functional programming to Python land
-
Provides a bunch of primitives to write declarative business logic
-
Enforces better architecture
-
Make your functions return something meaningful, typed, and safe!
Tags
- functional programming
- software architecture
- type safety
- too many ifs: bad
- monad/container value/type
- functional programming: in non-functional languages
- monad: Maybe
- business logic
- primitives
- declarative
- make it hard to get wrong/incorrect
- example
- see content below
- programming: return values / result objects that communicate a more precise/complete representation of the outcome
- unreadable
Annotators
URL
-
-
drylabs.io drylabs.io
-
Our mission is to allow people to make money via educational efforts and to dedicate the rest of their time to creating great open source products.
What does this mean exactly? "Our mission is to allow people to make money via educational efforts"
-
-
-
en.wikipedia.org en.wikipedia.org
-
Examples
-
despite initially appearing to be an appropriate and effective response to a problem, has more bad consequences than good ones
-
there are two key elements to an anti-pattern that distinguish it from a bad habit, bad practice, or bad idea
-
-
-
But so far everything brought up has just been about the relative advantages of checked exceptions, and that issue is closed. We won't do it.
-
I'm not a fan of listing exceptions functions can throw, especially here in Python, where it's easier to ask forgiveness than permission.
-
certainly I wouldn't want it to start telling me that I'm not catching these!
-
I'm not a fan of checking exceptions either
-
In my past life with Java, I've had mixed feelings about exception checking. It's saved me from some mistakes more than it's been annoying. Maybe the checking of exceptions could be controlled by some notion of "unchecked exceptions"?
Tags
- easier to ask forgiveness than permission
- making decisive/definite/bold decisions
- programming languages: requires verbosity / extra paperwork to explicitly list types/exceptions/...
- errors/warnings that may not apply to your case and be noisy/annoying to be warned about
- error/exception handling
- make bold decisions
- Python: the Python way
- checked exceptions
- design decision
- don't constantly revisit a decision
- intentional/well-considered decisions
Annotators
URL
-
-
www.python.org www.python.org
-
This PEP provides a standardized means to leverage existing tooling to package and distribute type information with minimal work and an ordering for type checkers to resolve modules and collect this information for type checking.
Tags
Annotators
URL
-
-
www.morozov.is www.morozov.is
-
include Dry::Monads::Do.for(:call)
-
Railway Oriented Programming is a way to gracefully handle errors in your application
-
This is how the same example would look like using raw monads:
-
Do notation provides an alternative to bind, which also flattens the code.
-
-
tineye.com tineye.com
-
-
boardgamegeek.com boardgamegeek.com
-
www.kickstarter.com www.kickstarter.com
-
let's be honest, print-and-play is A LOT of work (printing, cutting, laminating, sleeving, etc) and it is not everyone's cup of tea.
-
-
boardgamegeek.com boardgamegeek.comMaquis1
-
boardgamegeek.com boardgamegeek.comDEFCON 12
-
-
The game seems perfectly balanced, what is so rare for an assymétric game
-
-
www.kickstarter.com www.kickstarter.comDEFCON 12
-
The author will offer presentation/game sessions on Tabletopia, in French and English. In addition, the game will be freely available for players on Tabletopia as soon as the written rules are available.
-
-
-
www.metacritic.com www.metacritic.com
-
This is the perfect game when you are not wanting something with stakes or stress.
Tags
Annotators
URL
-
-
www.metacritic.com www.metacritic.comWarsaw1
-
Difficult enough to prove a worthy challenge, with an over-complexity that might have benefitted from a little self-restraint.
overly complex = unnecessarily complicated
-
-
www.metacritic.com www.metacritic.com
-
It seems like such a beautiful little visual novel and while I wasn’t expecting a masterpiece of localisation based on its low price, I was expecting to be able to read it. But that just cannot be done. Developers from Japan, China, Taiwan, Indonesia, and every other emerging game development centre through Asia-Pacific, listen to me carefully: You can have the most beautiful aesthetics and a heartwarming concept for your game. If the localisation isn’t going to be good, though, do not bother with an English release, because it is going to get reviews like this one. Make “invest in proper translation” your big resolution for 2021. I do not want to play any other games like Lily in the Hollow - Resurrection ever again.
-
-
www.metacritic.com www.metacritic.com#DRIVE1
-
The cars handling can be best explained as "its like steering a drunk sailor on a boat."
Tags
Annotators
URL
-
-
www.metacritic.com www.metacritic.com
-
This tedium would be unacceptable in an action game, but Windbound is a survival game. In survival games, death is supposed to mean something. Loss of progress represents the stakes; repetition is the barrier of entry.
-