Game scripting mastery 是一本不可多得的好书，除了写得啰嗦。
豆瓣网友 全棧法師张解靈 2018-08-01 16:37:13 写道：
说实话，难看。 但是内容完全没问题，就是实在太啰嗦了，即使英语原著也是...看得有点难受，想跳呢又怕错过好东西，想慢慢看呢又...还是慢慢啃吧 如果谁重排一个脱水版，我绝对打满分
另一个网友 TerryX 2017-01-06 18:44:19 写道：
We use Graylog to log everything, on Windows machines we also log into EventLog. I recently noticed for every exception I got two items in EventViewer, one is Logged by our code, and the other is logged by the .net runtime I guess. It is a little bit annoying. TLDR; here's the answer:
public override void OnException(ExceptionContext actionExecutedContext)
actionExecutedContext.ExceptionHandled = true;
actionExecutedContext.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
actionExecutedContext.Result = new ObjectResult(new ErrorResponse()
StatusCode = (HttpStatusCode) StatusCodes.Status500InternalServerError,
Message = actionExecutedContext.Exception.Message,
The key is this line
actionExecutedContext.ExceptionHandled = true;.
Occasionally, we will need to define
local used functions in a public procedure or a function. Fortunately, PL/SQL supports embedded functions. I spent more than an hour trying to find the correct way to use this feature. Yes. forgive me, I am a little dumb. According to my retries, the best position to put your local functions is sharp before the
BEGIN symbol. And here's a sample.
set serveroutput on;
CREATE OR REPLACE PROCEDURE tmp12345(v_full_name IN VARCHAR2) AS
-- local function definitaions start ---
FUNCTION FETCH_REAL_NAME(v_statement_name IN VARCHAR2) RETURN VARCHAR2
pattern VARCHAR2(100) := '^(Dr|Ms|Mx|Mr|Mrs)\s+';
-- replace possible multiple spaces to one space
full_name := TRIM(REGEXP_REPLACE(v_statement_name, '\s+', ' '));
IF (REGEXP_LIKE(full_name, pattern, 'i')) THEN
-- REGEXP_REPLACE(string, pattern [, replacement_string [, start_position [, nth_appearance [, match_parameter ] ] ] ])
RETURN REGEXP_REPLACE(full_name, pattern, '', 1, 0, 'i');
FUNCTION FETCH_MIDDLE_NAME(full_name IN VARCHAR) RETURN VARCHAR AS
middle_name := SUBSTR(full_name, INSTR(full_name, ' ') + 1, INSTR(full_name, ' ', 1, 2) - INSTR(full_name, ' ') - 1);
IF (LENGTH(middle_name) > 10) THEN
-- return initial instead
RETURN SUBSTR(middle_name, 1, 1);
-- local functions definitaions end ---
-- main logic here
localv := v_full_name;
Just record a few tips here:
[UseApprovalSubdirectory("Approvals")] can be used to set up the directory that saves the approval results.
It can be used for a test class or a test method.
For some reason, I was told an interesting github repo, The Gilded Rose Kata. It really grasps my attention. The code's behavior is correct, but both code quality and code style are terrible. The author of the repo made it so bad on purpose. So it is the best material to teach newbies how to refactor.
From the Readme file of the repo, I learnt some new tools, one is the text based approval test. I actually know that concept before many years ago, but never practiced it. I just found it is easy to setup and easy to run. It tests your code from a new angle. I believe it could belong to a kind of greybox test. You need to know the code to test, but you don't know too much like other unit test methods.
I have done the refactoring, and my result has been put on Github.com
- first approach is on the main branch https://github.com/shukebeta/GildedRose-Refactoring-Kata/tree/main/csharpcore
- a better approach is on the other branch https://github.com/shukebeta/GildedRose-Refactoring-Kata/tree/simple-factory-pattern-approch
Here are some good links, and I would update it timely.
Writing good tests for the gilded rose kata
Principles for agile test automation
The gilded rose refactoring kata
How to refactor gildedrose refactoring kata with simple factory pattern and strategy pattern